이 문제는 조합과 bfs 알고리즘을 활용하여 풀었습니다.
주의 해야할 사항은
Input >>
4 2
0 1 1 0
2 1 1 2
2 1 1 2
0 1 1 0
Output >>
2
와 같이 바이러스의 활성상태와 비활성상태의 전환인데요.
문제를 잘 읽어볼 필요가 있습니다.
~. 활성 바이러스가 비활성 바이러스가 있는 칸으로 가면 비활성 바이러스가 활성으로 변한다.
따라서 위와같은 케이스에서 처리를 해줘야 합니다.
소스는 다음과 같습니다.
package sw;
import java.io.*;
import java.util.*;
public class Main17142_연구소3 {
static int N,M,V,E;
static int[][] map;
static int[][] dir = // 우하좌상
static List<Pos> virusTotal;
static List<Pos> virusSelect;
static boolean[][] visit;
static boolean check(int x, int y) {
if(x>=0 && x<N && y>=0 && y<N)
return true;
else return false;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input = br.readLine().trim().split(" ");
N = Integer.parseInt(input[0]);
M = Integer.parseInt(input[1]);
virusTotal = new ArrayList<>();
virusSelect = new ArrayList<>();
map = new int[N][N];
V = 0;
String[] str = null;
for(int i=0; i<N; i++) {
str = br.readLine().trim().split(" ");
for(int j=0; j<N; j++) {
map[i][j] = Integer.parseInt(str[j]);
if(map[i][j]==2){
virusTotal.add(new Pos(i,j));
V++; // 총 바이러스 갯수 계산.
}else if(map[i][j]==0) E++; // bfs로 돌면서 공백의 갯수가 남아있을 때를 위해 계산.
}
}
/*
* vCm
*/
combination(0);
System.out.println(res==Integer.MAX_VALUE?-1:res);
}
static int res = Integer.MAX_VALUE,tmp;
static void combination(int n) {
if(virusSelect.size() == M) {
tmp = bfs();
if(res > tmp) res = tmp;
return;
}
if(n == V) return;
virusSelect.add(virusTotal.get(n));
combination(n+1);
virusSelect.remove(virusSelect.size()-1);
combination(n+1);
}
static int bfs() {
/*
* 선택된 바이러스로 bfs돌려서 최종 사이클(c)을 구합니다.
*/
Queue<Pos> qu = new LinkedList<>();
visit = new boolean[N][N];
Pos p = null;
int e = E;
int c = 0; // cycle
int size = 0;
if(e==0) return 0; // 빈공간이 없으므로 0 리턴.
for(int i=0; i<M; i++) {
p = virusSelect.get(i);
visit[p.x][p.y] = true;
qu.add(p);
}
int dx,dy;
while(!qu.isEmpty()) {
size = qu.size();
for(int i=0; i<size; i++) {
p = qu.poll();
for(int d=0; d<4; d++){
dx = p.x + dir[d][0];
dy = p.y + dir[d][1];
if(check(dx,dy) && !visit[dx][dy]) {
if(map[dx][dy]==0) {
visit[dx][dy] = true;
qu.add(new Pos(dx,dy));
e--;
}else if(map[dx][dy]==2) {
visit[dx][dy] = true;
qu.add(new Pos(dx,dy));
}
}
}
if(e==0) return c+1; // 한싸이클 더 돌기전에 리턴하므로 c+1
}
c++;
}
/*
* 공백이 하나라도 남아있을 때 MAX값 리턴
* 한싸이클 더 돌고 리턴하므로 c-1
*/
return e==0 ? c-1 : Integer.MAX_VALUE;
}
static class Pos{
int x,y;
public Pos(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "[x=" + x + "," + y + "]";
}
}
}
PREVIOUS[삼성기출]백준16235 - 나무 재테크