알고리즘/BOJ

백준 17822번 원판 돌리기

꾸준함. 2020. 5. 26. 21:44

문제 링크입니다: https://www.acmicpc.net/problem/17822

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀

www.acmicpc.net

여타 다른 삼성 코딩 테스트처럼 문제를 잘 읽고 그대로 구현하면 되는 문제였습니다.

원판을 시계방향 혹은 반시계방향으로 돌리기 때문에 저는 원판을 간단하게 구현하기 위해 덱 (deque)으로 구현했습니다. (해당 내용은 turnRullet 함수를 참고해주세요)

주의할 점은 덱으로 구현했기 때문에 인접한 요소를 찾을 때 덱의 front()와 덱의 back()이 인접했다고 표시하는 부분은 별도로 처리해줘야 합니다.

또한, 평균을 정수가 아닌 실수로 구하여 비교해야 한다는 점을 주의해야 합니다.

 

#include <iostream>
#include <queue>
#include <vector>
#include <deque>
using namespace std;
const int MAX = 50 + 1;
typedef struct
{
int y, x;
}Dir;
Dir moveDir[4] = { { 1, 0 },{ -1, 0 },{ 0, 1 },{ 0, -1 } };
int N, M, T;
int X, D, K;
deque<int> dq[MAX];
void turnRullet(void)
{
for (int x = X; x <= N; x += X)
{
for (int k = 0; k < K; k++)
{
if (D == 0)
{
int temp = dq[x].back();
dq[x].pop_back();
dq[x].push_front(temp);
}
else
{
int temp = dq[x].front();
dq[x].pop_front();
dq[x].push_back(temp);
}
}
}
}
bool eraseNumbers(void)
{
bool erasedNumbers = false;
// 인접한 수 처리
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
if (dq[i][j] == 0)
{
continue;
}
queue<pair<int, int>> q;
int value = dq[i][j];
q.push({ i, j });
bool visited[MAX][MAX] = { false, };
visited[i][j] = true;
vector<pair<int, int>> v;
while (!q.empty())
{
int y = q.front().first;
int x = q.front().second;
q.pop();
v.push_back({ y, x });
for (int d = 0; d < 4; d++)
{
int nextY = y + moveDir[d].y;
int nextX = x + moveDir[d].x;
// 위 아래는 인접 X
if (nextY == 0 || nextY > N)
{
continue;
}
// 양 옆 인접 O
if (nextX == -1)
{
nextX = M - 1;
}
else if (nextX == M)
{
nextX = 0;
}
if (visited[nextY][nextX])
{
continue;
}
if (dq[nextY][nextX] == value)
{
visited[nextY][nextX] = true;
q.push({ nextY, nextX });
}
}
}
// 인접한 숫자가 있을 경우에만 제거
if (v.size() >= 2)
{
erasedNumbers = true;
for (int k = 0; k < v.size(); k++)
{
int y = v[k].first;
int x = v[k].second;
dq[y][x] = 0;
}
}
}
}
return erasedNumbers;
}
void changeNumbers(void)
{
int sum = 0;
int cnt = 0;
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
if (dq[i][j] == 0)
{
continue;
}
sum += dq[i][j];
cnt++;
}
}
double average = (double)sum / cnt;
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
if (dq[i][j] == 0)
{
continue;
}
if (dq[i][j] > average)
{
dq[i][j]--;
}
else if (dq[i][j] < average)
{
dq[i][j]++;
}
}
}
}
int main(void)
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M >> T;
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
int num;
cin >> num;
dq[i].push_back(num);
}
}
for (int t = 0; t < T; t++)
{
cin >> X >> D >> K;
turnRullet();
bool flag = eraseNumbers();
if (flag)
{
continue;
}
changeNumbers();
}
int result = 0;
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
result += dq[i][j];
}
}
cout << result << "\n";
return 0;
}
view raw .cpp hosted with ❤ by GitHub

 

개발환경:Visual Studio 2017

 

지적, 조언, 질문 환영입니다! 댓글 남겨주세요~

반응형

'알고리즘 > BOJ' 카테고리의 다른 글

백준 17244번 아맞다우산  (0) 2020.05.28
백준 17837번 새로운 게임 2  (0) 2020.05.27
백준 16639번 괄호 추가하기 3  (2) 2020.05.26
백준 1408번 24  (0) 2020.05.26
백준 16638번 괄호 추가하기 2  (0) 2020.05.24