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

    댓글