HyeLog

백준_16926_배열 돌리기 1 본문

알고리즘

백준_16926_배열 돌리기 1

shj718 2022. 2. 15. 13:27

간단한 줄 알았는데 생각보다 복잡한 문제였다. 어떤 방향으로 for문을 돌릴지에 대해 좀 길게 고민했다.

이 문제는

 

1) 돌려야하는 사각형의 개수 (= min(N, M) / 2 )만큼 반복문을 돌리는 방법과

2) 사각형의 네 꼭짓점을 지정해서 그 범위로 반복문을 돌리는 방법

 

두가지로 풀이가 가능한데, 나는 2번째 방법으로 풀었다.

 

배열을 반시계 방향으로 돌리기 때문에, for문에서 i가 증가하는 방향은 그 방향의 반대여야한다. 사각형의 네 변을 각각 돌리는 순서도 반시계의 반대인 시계 방향으로 정했다.

즉, 가로 위 -> 세로 오른쪽 -> 가로 아래 -> 세로 왼쪽 순 (시계방향)으로 각각 for문을 돌려 총 4개의 for문을 사용했다.

 

처음에 tmp에 A[x4][y4]를 저장한 이유는, 이 같은 순서로 배열을 돌리면, 맨 마지막에 A[x4][y4-1]에 기존 A[x4][y4]의 값이 아닌 이미 배열을 돌린 후의 값이 들어가게 되기 때문이다. 따라서 마지막에 tmp 값으로 바꿔주는 작업이 필요하다!

 

네 꼭짓점은 이렇게 잡았다.

#include <iostream>
#define MAX 300
using namespace std;

int N, M, R, A[MAX][MAX];

void solve() { // 가로 위, 세로 오른쪽, 가로 아래, 세로 왼쪽 순! (시계방향)
	while (R--) {
		int x1 = 0, y1 = 0; // 나중에 x++, y++
		int x2 = N - 1, y2 = 0; // 나중에 x--, y++
		int x3 = N - 1, y3 = M - 1; // 나중에 x--, y--
		int x4 = 0, y4 = M - 1; // 나중에 x++, y--

		while (x1 < x2 && y1 < y4) {
			int tmp = A[x4][y4];
			for (int i = x4; i < x3; i++) { // 가로 위
				A[i][y4] = A[i + 1][y4];
			}
			for (int i = y3; i > y2; i--) { // 세로 오른쪽
				A[x3][i] = A[x3][i - 1];
			}
			for (int i = x2; i > x1; i--) { // 가로 아래
				A[i][y2] = A[i - 1][y2];
			}
			for (int i = y1; i < y4; i++) { // 세로 왼쪽
				A[x1][i] = A[x1][i + 1];
			}
			A[x4][y4 - 1] = tmp;
			x1++;
			y1++;
			x2--;
			y2++;
			x3--;
			y3--;
			x4++;
			y4--;
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> N >> M >> R;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> A[i][j];
		}
	}
	solve();
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cout << A[i][j] << ' ';
		}
		cout << '\n';
	}
	return 0;
}