$N\times N$정사각형 격자판이 있다. 각 칸에는 초기 얼음의 양이 주어진다. 이 격자판에서 할 ‘파이어스톰’이라는 연산이 정의되는데, 이 연산을 주어진 입력에 따라 했을 때 마지막에 남아있는 얼음의 양의 합과 가장 큰 연결된 얼음 덩어리 크기를 찾는 문제이다.
파이어스톰 연산은 다음과 같다. 주어진 변수 $L$에 대해서, 전체 격자를 $2^L \times 2^L$크기의 부분격자로 나눈 후 각 부분격자를 시계방향으로 회전 시킨다. 그 다음, 어떤 칸$(r,c)$에 인접(상하좌우)한 칸들 중 얼음이 있는 칸이 2개 이하라면 $(r,c)$의 얼음의 양을 1 줄인다.
접근
문제 설명이 다소 복잡하지만, 결국 핵심은 (1) 부분격자로 어떻게 나누고, 각 부분격자에서 회전은 어떻게 구현해야 하는지 (2) 가장 큰 연결된 얼음 덩어리 크기는 어떻게 구할지 이다.
(1)의 경우 두 개의 for문을 이용하여 먼저 각 부분격자의 가장 위쪽, 왼쪽 모서리의 좌표를 뽑아냈다. 이 점을 $(row, col)$이라 하면, 시계방향 90도 회전은 다음과 같이 구현할 수 있다. 임시배열 temp, 원래 배열board, 현재 부분격자의 크기 len이라 하면,
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
temp[row + j][col + len - 1 - i] = board[row + i][col + j];
}
}
이다. 기준점 $(row,col)$ 기준으로 좌표를 어떻게 표현하는지 그려서 생각해보면 어렵지 않다.
(2)의 경우 간단한 DFS이다. visited배열에 방문 여부를 저장하고, 모든 칸을 이중 for문으로 돌면서 아직 방문하지 않았다면 dfs(row, col)를 호출해주었다. 네 개의 방향을 살펴보아 유효한 좌표면 재귀적으로 호출하도록 구현하였다.
주의할 점
처음에 문제 설명과 테스트 케이스를 읽고 언제 얼음이 줄어드는지 이해가 잘 안되었다. 인접한 칸중 얼음이 있는 칸이 2개 이하면 얼음이 줄어드므로, 최소한 네 귀퉁이에서는 얼음이 줄어드게 된다.