문제 : https://www.acmicpc.net/problem/17822
[ 알고리즘풀이 ]
1. 원판을 회전할 때, 반시계 방향으로 k 만큼 회전은 시계방향으로 M - k 만큼 회전으로 바꿔 생각한다.
void turnCircle(int n, int d, int k) {
int temp[50] = {}, jump;
if(d == 0) // 시계방향
jump = k;
else
jump = M - k;
for (int i = 0; i < M; i++)
temp[(i + jump) % M] = map[n][i];
for (int i = 0; i < M; i++)
map[n][i] = temp[i];
return;
}
2. 회전을 모두 진행하고, 인접한 수를 체크한다.
- 같은 원판을 0 ~ M - 1 번 때까지 순회하며 앞쪽과 같은지 체크한다. ( 이때, Map이 이미 '0'으로 지워진 경우는 체크하지 않는다. )
- 같은 위치에서 원판을 순회하며 앞쪽과 같은지 체크한다. ( 이때, Map이 이미 '0'으로 지워진 경우는 체크하지 않는다. )
- checkMap 을 순회하며 인접한 수 중 같은 수가 존재하는지 count 하고 존재한다면 해당 map을 0으로 갱신하고, 존재하지 않는다면 평균을 구해 평균보다 크면 ++, 작으면 --를 해준다. 이때, 이미 map이 모두 0으로 갱신된 경우에는 인접한 수 중 같은 수가 존재하지 않고, 평균도 구할 수 없으므로 따로 check해야 한다. 그렇지 않으면 평균을 구하는 과정에서 0으로 나누게 되고 런타임 에러를 맛볼 수 있다...!! 즉, checkMap을 순회하며 check 된 애들을 count하고, check 되지 않았고 map이 0이 아닌 애들을 따로 count 해줘야한다.
#include<iostream>
using namespace std;
int N, M, T, x, d, k, map[51][50] = {};
int sumCircle(void) {
int sum = 0;
for (int i = 1; i <= N; i++)
for (int j = 0; j < M; j++)
sum += map[i][j];
return sum;
}
void checkSameNum(void) {
bool checkMap[51][50] = {};
// 원판마다 양옆체크
for (int i = 1; i <= N; i++) {
for (int j = 0; j < M - 1; j++)
if (map[i][j] != 0 && map[i][j] == map[i][j + 1])
checkMap[i][j] = checkMap[i][j + 1] = true;
if (map[i][0] != 0 && map[i][0] == map[i][M - 1])
checkMap[i][0] = checkMap[i][M - 1] = true;
}
// j 번째 수마다 앞뒤 원판체크
for (int j = 0; j < M; j++) {
for (int i = 1; i <= N - 1; i++)
if (map[i][j] != 0 && map[i][j] == map[i + 1][j])
checkMap[i][j] = checkMap[i + 1][j] = true;
}
// 같은 수가 있는지 없는지 계산.
int sum = 0, count1 = 0, count2 = 0;
for (int i = 1; i <= N; i++) {
for (int j = 0; j < M; j++) {
if (checkMap[i][j] == true)
count2++;
else if(checkMap[i][j] == false && map[i][j])
sum += map[i][j], count1++;
}
}
if (count2 != 0) { // 같은 수가 있다면 0으로 셋팅.
for (int i = 1; i <= N; i++)
for (int j = 0; j < M; j++)
if (checkMap[i][j])
map[i][j] = 0;
}
else { // 같은 수가 없다면
if (count1 == 0) // 이미 다 0으로 채워진 경우.
return;
int avg = sum / count1;
for (int i = 1; i <= N; i++)
for (int j = 0; j < M; j++){
if (map[i][j] == 0)
continue;
if (map[i][j] > avg)
map[i][j]--;
else if (map[i][j] < avg)
map[i][j]++;
else {
if (sum % count1 != 0)
map[i][j]++;
}
}
}
return;
}
void turnCircle(int n, int d, int k) {
int temp[50] = {}, jump;
if(d == 0) // 시계방향
jump = k;
else
jump = M - k;
for (int i = 0; i < M; i++)
temp[(i + jump) % M] = map[n][i];
for (int i = 0; i < M; i++)
map[n][i] = temp[i];
return;
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> N >> M >> T;
for (int i = 1; i <= N; i++)
for (int j = 0; j < M; j++)
cin >> map[i][j];
for (int i = 0; i < T; i++) {
cin >> x >> d >> k;
for (int j = x; j <= N; j += x)
turnCircle(j, d, k);
checkSameNum();
}
cout << sumCircle();
return 0;
}