[백준 17142] 연구소(Java)

최민길(Gale)·2023년 11월 16일
1

알고리즘

목록 보기
148/172

문제 링크 : https://www.acmicpc.net/problem/17142

이 문제는 bfs와 백트래킹을 이용하여 풀 수 있습니다.

우선 바이러스가 활성화될 수 있는 여러 위치들 중 M개만 활성화시켜야 하기 때문에 백트래킹을 이용하여 M개를 선택합니다. 그 후 활성화시킨 바이러스에서 bfs 탐색을 진행하여 0이 없을 경우 그 카운트 값의 최솟값을 계속 갱신합니다.

여기서 주의할 점은 0의 개수 카운트를 next 진행 중에 진행해야 한다는 점입니다. 큐에 들어가지 못하지만 현재 상태가 이미 바이러스가 확산이 다 된 상태라면 그 값을 리턴해야 하기 때문입니다.

다음은 코드입니다.

import javax.annotation.processing.SupportedSourceVersion;
import java.util.*;
import java.io.*;

class Main{
    static int N,M;
    static int[][] map;
    static boolean[][] check;
    static boolean[] virusCheck;
    static List<Virus> virusList = new ArrayList<>();
    static int res = Integer.MAX_VALUE, zero = 0;
    static int[] dy = {1,0,-1,0}, dx = {0,1,0,-1};

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        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) virusList.add(new Virus(i,j,0));
                else if(map[i][j] == 0) zero++;
            }
        }
        virusCheck = new boolean[virusList.size()];

        if(zero == 0) System.out.println(0);
        else{
            backtracking(0,0);
            if(res == Integer.MAX_VALUE) System.out.println(-1);
            else System.out.println(res);
        }
    }

    static void backtracking(int idx, int cnt){
        if(cnt == M){
            bfs();
            return;
        }

        for(int i=idx;i<virusCheck.length;i++){
            if(!virusCheck[i]){
                virusCheck[i] = true;
                backtracking(i+1,cnt+1);
                virusCheck[i] = false;
            }
        }
    }

    static void bfs(){
        check = new boolean[N][N];
        Queue<Virus> queue = new ArrayDeque<>();
        for(int i=0;i<virusCheck.length;i++){
            if(virusCheck[i]){
                Virus v = virusList.get(i);
                queue.add(v);
                check[v.y][v.x] = true;
            }
        }

        int cnt = zero;
        while(!queue.isEmpty()){
            Virus curr = queue.poll();

            for(int i=0;i<4;i++){
                int ny = curr.y + dy[i];
                int nx = curr.x + dx[i];
                if(ny<0 || ny>=N || nx<0 || nx>=N) continue;
                if(check[ny][nx] || map[ny][nx]==1) continue;

                if(map[ny][nx]==0) cnt--;

                if(cnt == 0){
                    res = Math.min(res, curr.cnt+1);
                    return;
                }

                check[ny][nx] = true;
                queue.add(new Virus(ny,nx,curr.cnt+1));
            }
        }

    }

    static class Virus{
        int y;
        int x;
        int cnt;

        Virus(int y, int x, int cnt){
            this.y = y;
            this.x = x;
            this.cnt = cnt;
        }
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글