처음에 떠올린 풀이는 (먼저 말해두지만 틀린 풀이입니다.)
1. 이중포문으로 칸 하나하나 검사한다.
2. 만약 치즈인 칸을 만나면 그 칸의 상하좌우를 보고 뚫려있는 곳(0)이면 그 칸에서 DFS를 시작한다.
3. DFS를 돌리다가 맵 바깥에 닿게 되면 바깥 공기이므로, 그렇게 바깥공기와 2번 닿으면 그 칸을 ArrayList에 넣어둔다.
4. 이중포문을 빠져나오면 ArrayList 담긴 좌표의 map 값을 0으로 바꾼다. (치즈 녹이기)
5. 위 과정을 치즈가 모두 없어질 때까지 반복한다.
라는 엄청난 말도 안되는 풀이를 생각했었다.
이렇게 풀면, map이 NxM 사이즈이고, 치즈의 개수가 K개 일때,
O(K^2NM)인 엄청난 시간 복잡도로 풀수 있다...
이 풀이로 풀면 메모리 초과가 났었다.
제대로 된 풀이는 다음과 같다.
민트색으로 표시된 부분만 DFS에서 방문하게 됨. 치즈 부분은 DFS로 방문하지 않기 때문에, 바깥공기가 아닌 빈공간도 방문할 수 없게 된다.
민트색 부분을 방문하고 상하좌우를 봤을 때, 치즈가 있으면 1 증가시키고 dfs 후에 3 이상의 값을 가지고 있는 치즈를 녹인다.
바깥 공기와 닿은 치즈를 검사할 때 DFS, BFS 중 무엇을 써도 상관없다.
코드는 다음과 같다.
import java.util.*;
import java.io.*;
class Main {
static int N, M;
static int[][] map;
static boolean[][] visited;
// 상하좌우 확인 용 dy, dx 배열
static int dy[] = {1, -1, 0, 0};
static int dx[] = {0, 0, -1, 1};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N+1][M+1];
visited = new boolean[N+1][M+1];
int count = 0; // 치즈의 수
// 격자 입력 받는 부분
for(int i=1; i<=N; ++i) {
st = new StringTokenizer(br.readLine());
for(int j=1; j<=M; ++j) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 1) ++count;
}
}
//
int turn = 0;
while(count > 0) { // count(치즈 수)가 0 될때까지 반복
turn++;
// visited 초기화
for(int i=0; i<=N; ++i) {
for(int j=0; j<=M; ++j){
visited[i][j] = false;
if(map[i][j] >=2) map[i][j] = 1;
}
}
dfs(1, 1); // (1, 1) 칸은 치즈가 없음이 보장된다.
// dfs에서 빠져나오면 맵을 쭉 검사한다.
for(int i=1; i<=N; ++i) {
for(int j=1; j<=M; ++j) {
if(map[i][j] >= 3) { // 3이상이면 바깥공기와 2면 이상 닿은 것임
map[i][j] = 0;
--count; // 치즈 수 감소
}
}
}
}
bw.write(turn + "\n"); bw.flush();
}
static void dfs(int y, int x) {
visited[y][x] = true;
for(int i=0; i<4; ++i) {
int ny = y + dy[i], nx = x + dx[i];
if(ny > N || ny <= 0 || nx <= 0 || nx > M) continue;
if(map[ny][nx] >= 1) {
map[ny][nx] += 1;
continue;
}
if(visited[ny][nx]) continue;
dfs(ny, nx);
}
}
}