연구소3


백준 [17142] 연구소3

문제보기
Alt text

풀이

  • 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;
   }
}