• [BOJ] 15683번 감시 Java 풀이

    2021. 6. 19.

    by. SDev

    728x90
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Queue;
    import java.util.StringTokenizer;
    
    public class Main {
    	static int n, m, blindSpot = 0;
    	static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
    	static List<int[]> list = new ArrayList<>();
    	static int[][] stat= {
    			{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1},
    			{1, 0, 1, 0}, {0, 1, 0, 1}, {1, 1, 0, 0}, {0, 1, 1, 0},
    			{0, 0, 1, 1}, {1, 0, 0, 1}, {1, 1, 1, 0}, {0, 1, 1, 1},
    			{1, 0, 1, 1}, {1, 1, 0, 1}, {1, 1, 1, 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());
    		
    		int[][] room = new int[n + 1][m + 1];
    		
    		for(int i = 1; i <= n; i++) {
    			st = new StringTokenizer(br.readLine());
    			for(int j = 1; j <= m; j++) {
    				room[i][j] = Integer.parseInt(st.nextToken());
    				
    				if(room[i][j] == 0) blindSpot++;
    				if(0 < room[i][j] && room[i][j] < 6) list.add(new int[] {i, j});
    			}
    		}
    		
    		bfs(room, blindSpot);
    		System.out.println(blindSpot);
    		
    	}
    	// 모든 cctv의 동작 조합을 시도
    	static void bfs(int[][] room, int blindSpot) {
    		Queue<Info> q = new LinkedList<>();
    		q.add(new Info(blindSpot, room));
    		
    		for(int i = 0; i < list.size(); i++) {
    			int qLen = q.size();
    			
    			for(int t = 0; t < qLen; t++) {
    				Info m = q.poll();
    				int bs = m.blindSpot;
    				int row = list.get(i)[0];
    				int col = list.get(i)[1];
    				
    				if(room[row][col] == 1) {
    					q.add(cctv(m.room, row, col, bs, stat[0]));
    					q.add(cctv(m.room, row, col, bs, stat[1]));
    					q.add(cctv(m.room, row, col, bs, stat[2]));
    					q.add(cctv(m.room, row, col, bs, stat[3]));
    				}
    				if(room[row][col] == 2) {
    					q.add(cctv(m.room, row, col, bs, stat[4]));
    					q.add(cctv(m.room, row, col, bs, stat[5]));
    				}
    				if(room[row][col] == 3) {
    					q.add(cctv(m.room, row, col, bs, stat[6]));
    					q.add(cctv(m.room, row, col, bs, stat[7]));
    					q.add(cctv(m.room, row, col, bs, stat[8]));
    					q.add(cctv(m.room, row, col, bs, stat[9]));
    				}
    				if(room[row][col] == 4) {
    					q.add(cctv(m.room, row, col, bs, stat[10]));
    					q.add(cctv(m.room, row, col, bs, stat[11]));
    					q.add(cctv(m.room, row, col, bs, stat[12]));
    					q.add(cctv(m.room, row, col, bs, stat[13]));
    				}
    				if(room[row][col] == 5) {
    					q.add(cctv(m.room, row, col, bs, stat[14]));
    				}
    			}
    		}
    	}
    	
    	// cctv를 동작시키고 결과와 blindSpot 개수를 세어 반환
    	static Info cctv(int[][] room, int row, int col, int num, int[] status) {
    		int[][] result = copy(room);
    		
    		// 비추는 방향마다 벽을 만나거나 방을 벗어날 때까지 비추도록 함
    		for(int i = 0; i < 4; i++) {
    			// 현재 방향을 비추지 않으면 continue
    			if(status[i] == 0) continue;
    			int nxtRow = row;
    			int nxtCol = col;
    			
    			while(true) {
    				nxtRow = nxtRow + dx[i];
    				nxtCol = nxtCol + dy[i];
    				
    				// 다음 위치가 room 내부를 벗어나거나 벽이라면 이동할 수 없음
    				if(nxtRow < 1 || nxtRow > n || nxtCol < 1 || nxtCol > m) break;
    				if(result[nxtRow][nxtCol] == 6) break;
    				
    				if(result[nxtRow][nxtCol] == 0) {
    					result[nxtRow][nxtCol] = 8;
    					num--;
    				}
    			}
    		}
    		
    		if(blindSpot > num) blindSpot = num;
    		return new Info(num, result);
    	}
    	
    	static int[][] copy(int[][] room){
    		int[][] result = new int[n + 1][m + 1];
    		for(int i = 0; i<= n; i++) {
    			System.arraycopy(room[i], 0, result[i], 0, m + 1);
    		}
    		return result;
    	}
    }
    
    class Info{
    	int blindSpot;
    	int[][] room;
    	
    	public Info(int blindSpot, int[][] room) {
    		this.blindSpot = blindSpot;
    		this.room = room;
    	}
    }
    

    댓글