문제 : 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;
}

 

+ Recent posts