Question
문제 해설
- 크기가 NxN인 연구소에 빈칸(0), 바이러스틑 놓을 수 있는 빈칸(2), 벽(1)이 존재
- 승원이는 M개의 바이러스를 연구소에 놓고 이를 퍼트리려함
- 개수 : M <= 바이러스를 높을 수 있는 칸(2)
- 바이러스는 1초에 상, 하, 좌, 우로 퍼짐
- 바이러스가 모든 빈 칸에 퍼뜨려지는 최소 시간은?
Solution
풀이 접근 방법
- 바이러스가 상, 하, 좌, 우로 퍼짐 = BFS
- M개의 바이러스를 심음 : 심는 위치 조합
정답 코드
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
static int N, M;
static int[][] map;
static ArrayList<Point> virus;
static int[] dx = new int[] { 0, 0, 1, -1 }, dy = new int[] { 1, -1, 0, 0 };
static int result = Integer.MAX_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] info = br.readLine().split(" ");
N = Integer.parseInt(info[0]);
M = Integer.parseInt(info[1]);
map = new int[N][N];
virus = new ArrayList<Point>();
int zeroSpace = 0;
for (int i = 0; i < N; i++) {
map[i] = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
for (int j = 0; j < N; j++) {
if (map[i][j] == 2) {
virus.add(new Point(i, j));
map[i][j] = 0;
zeroSpace++;
} else if (map[i][j] == 1) {
map[i][j] = -1;
} else {
zeroSpace++;
}
}
}
if (zeroSpace == 0) {
System.out.println(0);
} else {
pickVirus(new boolean[virus.size()], 0, M);
System.out.println(result == Integer.MAX_VALUE ? -1 : result);
}
}
public static void pickVirus(boolean[] visited, int start, int r) {
if (r == 0) {
Point[] picked = new Point[M];
int idx = 0;
for (int i = 0; i < visited.length; i++) {
if (visited[i]) {
picked[idx++] = virus.get(i);
}
}
int[][] copyMap = spreadVirus(picked);
result = Math.min(result, checkVirus(copyMap));
return;
}
for (int i = start; i < virus.size(); i++) {
visited[i] = true;
pickVirus(visited, i + 1, r - 1);
visited[i] = false;
}
}
public static int[][] spreadVirus(Point[] picked) {
Queue<Point> queue = new LinkedList<Point>();
int[][] copyMap = new int[N][N];
boolean[][] visited = new boolean[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
copyMap[i][j] = map[i][j];
}
}
for (int i = 0; i < picked.length; i++) {
Point pick = picked[i];
copyMap[pick.x][pick.y] = -2;
visited[pick.x][pick.y] = true;
queue.add(pick);
}
while (!queue.isEmpty()) {
Point curV = queue.poll();
for (int i = 0; i < 4; i++) {
int nx = curV.x + dx[i];
int ny = curV.y + dy[i];
int newValue = copyMap[curV.x][curV.y] == -2 ? 1 : copyMap[curV.x][curV.y] + 1;
if (isIn(nx, ny) && !visited[nx][ny]) {
copyMap[nx][ny] = newValue;
visited[nx][ny] = true;
queue.add(new Point(nx, ny));
}
}
}
return copyMap;
}
public static int checkVirus(int[][] copyMap) {
int sec = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (copyMap[i][j] == 0) {
return Integer.MAX_VALUE;
}
sec = Math.max(sec, copyMap[i][j]);
}
}
return sec;
}
public static boolean isIn(int x, int y) {
if (0 <= x && x < N && 0 <= y && y < N && map[x][y] != -1) {
return true;
}
return false;
}
}