본문 바로가기

백준/삼성기출

연구소3 (Java)

728x90

package Samsung;

import java.io.*;
import java.util.*;

public class 연구소3 {

	static int n,m;
	static StringTokenizer st;
	static int[][]arr;
	static ArrayList<Pair>virus;
	static boolean check[][];
	static boolean tmp[][];
	static int answer=Integer.MAX_VALUE;
	
	static int[] dx = {-1,1,0,0};
	static int[] dy = {0,0,-1,1};
	
	static class Pair{
		
		int x,y;
		Pair(int x, int y){
			this.x =x;
			this.y = y;
		}
		
	}
	
	public static boolean cango(int x, int y) {
		
		return x>=0 && x<n && y>=0 && y<n;
	}
	
	public static int bfs(ArrayList<Pair>list) {
		
		Queue<Pair>q = new LinkedList<>();
		
		for(int t=0; t<list.size(); t++) {
			
			Pair p = list.get(t);
			q.add(p);
		}
		
		int time =0;
		
			while(!q.isEmpty()) {
				
				int sz =q.size();

				for(int i=0; i<sz; i++) {
				
				Pair pp =q.poll();
				int x = pp.x;
				int y = pp.y;
				
				
				for(int l=0; l<4; l++) {
					
					int nx =x+dx[l];
					int ny =y+dy[l];
					
					if(cango(nx,ny)&&arr[nx][ny]!=1) {
						
						//중요!! 
						if(check[nx][ny]==true && arr[nx][ny]==0)continue; //이미 체크되고 빈칸인경우는 탐색을 멈춘다
						if(arr[nx][ny]==2)arr[nx][ny]=0; // 바이러스는기존에 체크되었기 때문에 true라도 탐색을 더 진행한다
														 // 시간초과해결: 단 한번만 큐에넣고 탐색을 해야한다 그래서 한번 방문했을때 arr의 nx,ny를 0으로만들어 다시 탐색 하지 않도록한다
						q.add(new Pair(nx,ny));
						check[nx][ny]=true;
						
					}
				}
				
				if(checkAll()) {
					return time+1;
				}
				
				}	
				
				time++;
				
			}
			
	//		System.out.println(time);
			

				return -1;
			
		
	}
	
	public static boolean checkAll() {
		
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				
				if(arr[i][j]!=1 && check[i][j]==false) {
					return false;
				}
				
			}
		}
		
		return true;
	}
	
	public static void pick(int idx, ArrayList<Pair>list ) { //여러개의 바이러스중 m개의 바이러스를 고른다
		
		
		if(list.size()==m) {
			
			int res = bfs(list); // 모든 칸을 바이러스로 감염심키는데 필용한 시간
			check = new boolean[n][n]; //바이러스 감영여부를 알려주는 배열
			
			for(int i=0; i<n; i++) {
				for(int j=0; j<n; j++) {
					check[i][j]=tmp[i][j];
					if(tmp[i][j])arr[i][j]=2; //기존의 바이러스를 0으로 만들었던것을 다시 2로 복구시킨다
				}
			}
			
			if(res==-1) return;
			answer = Math.min(res, answer );
			return;
			
		}
		
		for(int i=idx; i<virus.size(); i++) {
			
			list.add(virus.get(i));
			pick(i+1,list);
			list.remove(list.size()-1);
	
		}
		
	}
	
	
	public static void main(String[]args) throws IOException {
		
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		
		check = new boolean[n][n];
		tmp= new boolean[n][n];
		arr = new int[n][n];
		virus = new ArrayList<>();
		
		for(int i=0; i<n; i++) {
			st =  new StringTokenizer(br.readLine());
			for(int j=0; j<n; j++) {
				
				arr[i][j]=Integer.parseInt(st.nextToken());
				if(arr[i][j]==2) {
					virus.add(new Pair(i,j));
					check[i][j]=true;
					tmp[i][j]=true;
				}
			}
		
		}
		
		if(checkAll()) {  //바이러스가 이미 다 전파되었는지를 확인한다
			System.out.println(0);
			return;
		}
		
		pick(0,new ArrayList<>()); 
		
		if(answer == Integer.MAX_VALUE) {answer=-1;}
		System.out.println(answer);
		
		
	}
	
	
}

- 활성 바이러스가 아니었던게 활성이 되고나서 다시 해당 바이러스를 방문하지 않도록 처리해야 시간초과 안난다.

'백준 > 삼성기출' 카테고리의 다른 글

새로운 게임2  (0) 2021.10.06
게리맨더링2(Java)  (0) 2021.10.04
인구이동(JAVA)  (0) 2021.10.02
마법사상어와 블리자드  (0) 2021.09.29
로봇청소기  (0) 2021.09.29