알고리즘/[문제풀이] BOJ
[BOJ] 17822 - 원판 돌리기
be-lgreen
2021. 10. 21. 23:09
https://www.acmicpc.net/problem/17822
17822번: 원판 돌리기
반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀
www.acmicpc.net
난이도
구현 / 난이도 ⭐️⭐️ / 1시간30분 소요
주의할 점
크기 어렵지 않으나, 실수한 부분이 많아서 오래걸렸다.
이런 문제의 경우 단계단계 구현결과를 확인하는게 좋은 것 같다.
#include <stdio.h>
#include <vector>
#include <set>
#include <utility>
using namespace std;
int N, M, T; // n: 원판 갯수 m: 원판 위 숫자 갯수 T : 원판 돌리기 케이스
int arr[51][51] = {0};
void rotate(int x, int d, int k)
{
int c_arr[51] = {0};
for (int i = 0; i < M; i++)
{
c_arr[i] = arr[x][i];
}
int new_index;
if (d == 0)
{ // 시계방향
// 1 2 3 4 5
// 4 5 1 2 3
for (int i = 0; i < M; i++)
{
new_index = i + k;
if (new_index > M - 1) // check point1) 부등호 조심
new_index -= M;
arr[x][new_index] = c_arr[i];
}
}
else if (d == 1)
{
// 1 2 3 4 5
// 3 4 5 1 2
for (int i = 0; i < M; i++)
{
new_index = i - k;
if (new_index < 0)
new_index += M;
arr[x][new_index] = c_arr[i];
}
}
}
void remove_number()
{
set<pair<int, int> > ss;
// 세로로 확인
for (int i = 0; i < M; i++)
{
int pre_num = arr[1][i];
for (int j = 2; j <= N; j++)
{
if (arr[j][i] != pre_num)
{
pre_num = arr[j][i];
}
else if (arr[j][i] == pre_num)
{
if (arr[j][i] == 0)
continue;
ss.insert(make_pair(j - 1, i));
ss.insert(make_pair(j, i));
}
}
}
// 가로로 확인
for (int i = 1; i <= N; i++)
{
int pre_num = arr[i][M - 1];
for (int j = 0; j < M; j++)
{
if (arr[i][j] != pre_num)
{
pre_num = arr[i][j];
}
else if (arr[i][j] == pre_num)
{
if (arr[i][j] == 0)
continue;
ss.insert(make_pair(i, j));
if (j == 0)
{
ss.insert(make_pair(i, M - 1));
}
else
{
ss.insert(make_pair(i, j - 1));
}
}
}
}
if (!ss.empty())
{
set<pair<int, int> >::iterator iter;
int x, y;
for (iter = ss.begin(); iter != ss.end(); iter++)
{
x = iter->first;
y = iter->second;
arr[x][y] = 0;
}
}
else
{
int total = 0;
int total_cnt = 0;
float avg = 0;
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
if (arr[i][j] == 0)
continue;
total += arr[i][j];
total_cnt += 1;
}
}
avg = (float)total / (float)total_cnt; // check pont2) 22/6일 경우 float으로 계산해야지 3.xxx라는 수가 나오는데, 3은 3.xxx보다 작다.
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
if (arr[i][j] == 0)
continue;
if ((float)arr[i][j] > avg)
{
arr[i][j] -= 1;
}
else if (float(arr[i][j]) < avg)
{
arr[i][j] += 1;
}
}
}
}
}
int main()
{
scanf("%d %d %d", &N, &M, &T);
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
scanf("%d", &arr[i][j]);
}
}
int X, D, K;
for (int i = 0; i < T; i++)
{
scanf("%d %d %d", &X, &D, &K);
for (int j = X; j <= N; j += X)
{
// X의 배수 원판을 D방향을 K만큼 돌린다.
rotate(j, D, K);
}
remove_number();
}
int result = 0;
for (int i = 1; i <= N; i++)
{
for (int j = 0; j < M; j++)
{
if (arr[i][j] != 0)
{
result += arr[i][j];
}
}
}
printf("%d", result);
}