감시

LJM·2023년 9월 5일
0

백준풀기

목록 보기
219/259

https://www.acmicpc.net/problem/15683

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

public class Main {
    static int N, M; // 사무실의 세로와 가로 크기
    static int[][] board; // 사무실의 상태를 저장하는 2차원 배열
    static List<int[]> cctvs = new ArrayList<>(); // CCTV의 위치와 종류를 저장하는 리스트
    // 각 CCTV의 방향을 나타내는 배열
    static int[][] directions = {
            {},
            {0, 1, 2, 3},
            {0, 1},
            {0, 1, 2, 3},
            {0, 1, 2, 3},
            {0, 1, 2, 3}
    };
    // 상, 하, 좌, 우 방향을 나타내는 배열
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {0, 0, -1, 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());
        board = new int[N][M];

        // 사무실의 상태 입력 받기
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
                // CCTV의 위치와 종류 저장
                if (1 <= board[i][j] && board[i][j] <= 5) {
                    cctvs.add(new int[]{i, j, board[i][j]});
                }
            }
        }

        // 사각 지대의 최소 크기 출력
        System.out.println(dfs(0, board));
    }

    // DFS를 사용하여 모든 CCTV의 방향을 설정하고 사각 지대의 크기를 반환
    static int dfs(int idx, int[][] prevBoard) {
        int[][] board = new int[N][M];
        for (int i = 0; i < N; i++) {
            board[i] = Arrays.copyOf(prevBoard[i], M);
        }

        // 모든 CCTV의 방향을 설정한 경우
        if (idx == cctvs.size()) {
            int cnt = 0;
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (board[i][j] == 0) {
                        cnt++;
                    }
                }
            }
            return cnt;
        }

        int[] cctv = cctvs.get(idx);
        int x = cctv[0], y = cctv[1], type = cctv[2];
        int min = Integer.MAX_VALUE;

        // 현재 CCTV의 모든 방향에 대해 탐색
        for (int dir = 0; dir < 4; dir++) {
            //if (type == 2 && dir > 1) break;
            int[][] tempBoard = new int[N][M];
            for (int i = 0; i < N; i++) {
                tempBoard[i] = Arrays.copyOf(board[i], M);
            }
            watch(x, y, tempBoard, type, dir);
            min = Math.min(min, dfs(idx + 1, tempBoard));
        }

        return min;
    }

    // CCTV의 방향에 따라 감시 영역을 업데이트
    static void watch(int x, int y, int[][] board, int type, int dir) {
        switch (type) {
            case 1:
                update(x, y, board, dir);
                break;
            case 2:
                update(x, y, board, (dir*2)% 4);
                update(x, y, board, (dir*2 + 1)% 4);
                break;
            case 3:
                update(x, y, board, dir);
                int sdir = 0;
                if(dir == 0)
                    sdir = 3;
                else if(dir == 3)
                    sdir = 1;
                else if(dir == 1)
                    sdir = 2;
                else if(dir == 2)
                    sdir = 0;
                update(x, y, board, sdir);
                break;
            case 4:
                update(x, y, board, dir);
                update(x, y, board, (dir + 1) % 4);
                update(x, y, board, (dir + 2) % 4);
                break;
            case 5:
                update(x, y, board, dir);
                update(x, y, board, (dir + 1) % 4);
                update(x, y, board, (dir + 2) % 4);
                update(x, y, board, (dir + 3) % 4);
                break;
        }
    }

    // 주어진 방향으로 감시 영역을 업데이트
    static void update(int x, int y, int[][] board, int dir) {
        int nx = x, ny = y;
        while (true) {
            nx += dx[dir];
            ny += dy[dir];
            if (nx < 0 || nx >= N || ny < 0 || ny >= M || board[nx][ny] == 6) {
                break;
            }
            if (board[nx][ny] == 0) {
                board[nx][ny] = -1;
            }
        }
    }
}
profile
게임개발자 백엔드개발자

0개의 댓글