연구소에서 0(빈 칸), 1(벽), 2(바이러스)가 주어진다.
빈 칸 중 3곳을 벽으로 설치한 뒤, 모든 바이러스가 퍼지고 난 뒤
안전 영역(0의 개수)의 최대값을 구하는 문제.
N, M ≤ 8 → 64칸
모든 칸이 빈칸일 때
→ 벽 3개를 세우는 조합
BFS는 최대 64칸 전체를 한 번씩 방문 → O(64)
안전영역 계산도 O(64)
즉 조합 1개당 약 O(64)
약 260만 연산 → Java 2초 제한 충분히 통과(넉넉)
(일반적으로 자바는 1억 연산 ≈ 약 1초로 잡는다.)
➡ 2.6M은 전체 제한 2초에서 1/40도 안 되는 수준.
package algo.ct.M12;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class BOJ_14502_연구소_G5 {
static int N, M;
static int[][] arr;
static int[][] tmpArr;
static int maxSafe = 0;
static int[] dx = {-1, 1, 0, 0};
static int[] dy = {0, 0, -1, 1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
arr = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++)
arr[i][j] = Integer.parseInt(st.nextToken());
}
setWall(0);
System.out.println(maxSafe);
}
// 3개의 벽을 세우는 백트래킹
static void setWall(int count) {
if (count == 3) {
getVirus();
return;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 1;
setWall(count + 1);
arr[i][j] = 0;
}
}
}
}
// BFS로 바이러스 확산
static void getVirus() {
tmpArr = new int[N][M];
// 배열 복사
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
tmpArr[i][j] = arr[i][j];
Queue<int[]> q = new LinkedList<>();
// 바이러스 위치 큐에 추가
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (tmpArr[i][j] == 2) {
q.add(new int[]{i, j});
}
}
}
// BFS
while (!q.isEmpty()) {
int[] cur = q.poll();
for (int d = 0; d < 4; d++) {
int nx = cur[0] + dx[d];
int ny = cur[1] + dy[d];
if (nx < 0 || ny < 0 || nx >= N || ny >= M)
continue;
if (tmpArr[nx][ny] != 0)
continue;
tmpArr[nx][ny] = 2;
q.add(new int[]{nx, ny});
}
}
// 안전 영역 계산
int safe = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
if (tmpArr[i][j] == 0) safe++;
maxSafe = Math.max(maxSafe, safe);
}
}