출처:https://www.acmicpc.net/problem/16926
문제를 이해하기는 어렵지 않지만, 생각보다 구현이 어려운 문제이다. 배열을 돌렸을 때, 겹치는 부분을 어떻게 처리할 것인지 배열을 어떤 방법으로 돌릴 것인지 많은 고민을 해야하는 문제였다.
그리고, min(N,M) mod 2 =0
이 조건이 생각보다 큰 힌트를 주는 조건이다.
이 조건이 뭘 의미하는지 몰라서, 몇개 그려보면 쉽게 알 수 있게 된다.
(3,3) , (5,5)와 같은 배열들은 생각할 필요없이 min(N,M) mod 2=0 인 board들은 이쁘게 안의 rotate해야 할 작은 배열들이 나오게 된다.
시작점은 프로그램을 짜는 사람이 편한대로 잡으면 되지만, 나는 (0,0),(1,1)...과 같이 제일 왼쪽 점을 시작점으로 잡아주었다.
그다음, 배열을 돌리는 문제는 코드를 구현하다보면 헷갈리는 경우가 많으므로, 한 방향을 정해서 쭉 코드를 짜는게 편리하다. 그래서, 나는 시작점이 제일 왼쪽이니까 아래의 그림과 같이 짰다.( 배열을 돌릴 때 반복문을 시작점부터 돌리기 때문에, 시작점을 제일 먼저 덮어버리고, 비는 곳이 어딘지 확인하면서 돌리는 방향이 편하다. )
#include <bits/stdc++.h>
#define fastio cin.tie(0)->sync_with_stdio(0)
using namespace std;
int N, M, R;
// <- 아래 -> 위
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int board[301][301];
void chk_array()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
cout << board[i][j] << ' ';
}
cout << '\n';
}
}
void rotate()
{
for (int i = 0; i < min(N, M) / 2; i++)
{
int start_x = i;
int start_y = i;
// 나중에 겹치는 부분 추가해줄 value
int value = board[start_x][start_y];
int dir = 0;
while (dir < 4)
{
int nx = start_x + dx[dir];
int ny = start_y + dy[dir];
// 자기자신으로 돌아오면 종료
if (nx == i && ny == i)
break;
// 범위 안이라면
if (i <= nx && nx < N - i && i <= ny && ny < M - i)
{
board[start_x][start_y] = board[nx][ny];
start_x = nx;
start_y = ny;
}
// 범위 밖이라면, 다음 방향
else
dir++;
}
// 각 박스마다 겹치는 부분
board[i + 1][i] = value;
}
}
int main()
{
fastio;
cin >> N >> M >> R;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
cin >> board[i][j];
}
}
while (R--)
{
rotate();
}
chk_array();
return 0;
}