백준 [17142] 연구소3
문제보기
풀이
- choice() : 조합을 이용하여 활성 바이러스 선택 후, -1로 초기화 된 chk 맵 만들고 활성바이러스 큐에 넣기.
- hour() : 지도에 바이러스를 활성시켜보고 시간체크
소스코드
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.List;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int N, M;
static int[][] map;
static List<int[]> virus;
static int[] dx = { -1, 1, 0, 0 };
static int[] dy = { 0, 0, -1, 1 };
static int ans;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
virus = new ArrayList<>();
N = Integer.parseInt(st.nextToken()); // 연구소 크기
M = Integer.parseInt(st.nextToken()); // 바이러스의 개수
map = new int[N][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if (map[i][j] == 2)
virus.add(new int[] { i, j });
}
}
ans = 987654321;
choice(new int[M][2], 0, 0);
if (ans == 987654321) {
ans = -1;
}
System.out.println(ans);
}
public static void choice(int[][] c, int idx, int cnt) {
if (idx == M) {
// M개의 바이러스 선택. 이제 시간을 구할 차례
Queue<int[]> q = new LinkedList<>();
int[][] chk = new int[N][N];
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++){
chk[i][j]=-1;
}
}
for (int i = 0; i < M; i++) {
q.add(c[i]);
chk[c[i][0]][c[i][1]]=0;
}
hour(q,chk);
return;
}
if (cnt == virus.size())
return;
c[idx] = virus.get(cnt);
choice(c, idx + 1, cnt + 1);
choice(c, idx, cnt + 1);
}
public static void hour(Queue<int[]> q, int[][] chk) {
while (!q.isEmpty()) {
int[] v = q.poll();
for (int i = 0; i < 4; i++) {
int x = v[0] + dx[i];
int y = v[1] + dy[i];
// map이 빈칸일때는 진행하는데 같거나 작으면 안감.
if (isRange(x, y) && map[x][y] != 1 && chk[x][y] == -1) {
chk[x][y] = chk[v[0]][v[1]] + 1;
q.add(new int[] { x, y });
}
}
}
int max = 0;
boolean flag = true;
loop:for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j] == 0 && chk[i][j] == -1) { // 모두 퍼트려지지 않은 경우
flag=false;
break loop;
}
if (max < chk[i][j] && map[i][j]==0) {
max = chk[i][j];
}
}
}
if (flag)
ans = Math.min(ans, max);
}
public static boolean isRange(int x, int y) {
return x >= 0 && y >= 0 && x < N && y < N;
}
}