[백준] 감시

2025. 5. 25. 16:36·Algorithm/백준

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

 

접근 방식

시간복잡도 최악의 케이스에는: 4^8 * 8 * 8으로, 1초에 충분히 풀어낼 수 있다.

 

문제를 풀며 헷갈렸던 것 두가지는, 어떻게 각 cctv 방향 경우의 수 만큼 백트래킹을 돌려주는 것과 board의 값들을 계속해서 업데이트 시켜주는 것이 헷갈렸다.

 

경우의 수는, 단순히 해당 cctv의 direction 경우의 수를 가져와서 for문을 돌면 해결되었고, 배열 복사같은 경우 문제가 되었다.

 

int[][] tmp = copyBoard(board);

public static int[][] copyBoard(int[][] board) {
    int[][] tmp = new int[n][m];
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            tmp[i][j] = board[i][j];
        }
    }
    return tmp;
}

 

기존에는 파라미터 없이 int[][] tmp = copyBoard() 이렇게 해주고 있었는데, 이런식으로 하면 계속해서 원본 배열만 복사하고 초기화하고 이런 형식이라 지속적으로 업데이트를 해줘야한다. 그렇기 때문에, 값을 저장할 수 있는 매개변수를 통해 전달해주었다. 

 

계속해서 답이 안나와서 많이 해맸는데, 정답은 여기에 있었어서 이 부분을 앞으로 주의깊게 확인해야겠다. 

 

풀이

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class boj15683 {
    static int n, m;
    static int[][] board;
    static List<CCTV> cctvList = new ArrayList<>();
    static int[] dx = {0, 1, 0, -1};
    static int[] dy = {1, 0, -1, 0};
    static int res = Integer.MAX_VALUE;
    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());
                if (board[i][j] == 1) cctvList.add(new CCTV(1, 4, new int[]{i,j}));
                else if (board[i][j] == 2) cctvList.add(new CCTV(2, 2, new int[]{i,j}));
                else if (board[i][j] == 3) cctvList.add(new CCTV(3, 4, new int[]{i,j}));
                else if (board[i][j] == 4) cctvList.add(new CCTV(4, 4, new int[]{i,j}));
                else if (board[i][j] == 5) cctvList.add(new CCTV(5, 1, new int[]{i,j}));
            }
        }

        dfs(0, board);
        System.out.println(res);
    }

    public static void dfs(int depth, int[][] board) {
        if (depth == cctvList.size()) {
            // printBoard(board);
            res = Math.min(res, calculateArea(board));
            return;
        }

        CCTV cur = cctvList.get(depth);
        for(int i = 0; i < cur.dir; i++) { // cctv의 방향 케이스만큼 순회
            int[][] tmp = copyBoard(board);
            apply(tmp, cur, i);
            dfs(depth + 1, tmp);
        }
    }

    public static void apply(int[][] tmp, CCTV cur, int dir) {
        int type = cur.type;

        if (type == 1) {
            applyBoard(tmp, cur, dir);
        }

        else if (type == 2) {
            applyBoard(tmp, cur, dir);
            applyBoard(tmp, cur, (dir + 2) % 4);
        }

        else if (type == 3) {
            applyBoard(tmp, cur, (dir + 3) % 4);
            applyBoard(tmp, cur, dir);
        }

        else if (type == 4) {
            applyBoard(tmp, cur, (dir + 3) % 4);
            applyBoard(tmp, cur, (dir + 2) % 4);
            applyBoard(tmp, cur, dir);
        }

        else if (type == 5) {
            applyBoard(tmp, cur, (dir + 3) % 4);
            applyBoard(tmp, cur, (dir + 2) % 4);
            applyBoard(tmp, cur, (dir + 1) % 4);
            applyBoard(tmp, cur, dir);
        }
    }

    public static void applyBoard(int[][] tmp, CCTV cur, int dir) {
        int x = cur.pos[0];
        int y = cur.pos[1];

        while (true) {
            int nx = x + dx[dir];
            int ny = y + dy[dir];

            if (nx < 0 || ny < 0 || nx >= n || ny >= m) break;
            if (tmp[nx][ny] == 6) break;
            if (tmp[nx][ny] == 0) tmp[nx][ny] = -1;
            x = nx;
            y = ny;
        }
    }

    public static int calculateArea(int[][] board) {
        int area = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if (board[i][j] == 0) area++;
            }
        }
        return area;
    }

    public static void printBoard(int[][] tmp) {
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                System.out.print(tmp[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }

    public static int[][] copyBoard(int[][] board) {
        int[][] tmp = new int[n][m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                tmp[i][j] = board[i][j];
            }
        }
        return tmp;
    }

    public static class CCTV {
        public int type;
        public int dir;
        public int[] pos;
        public CCTV(int type, int dir, int[] pos) {
            this.type = type;
            this.dir = dir;
            this.pos = pos;
        }
    }
}

'Algorithm > 백준' 카테고리의 다른 글

연산자 끼워넣기, 스타트와 링크  (1) 2025.06.03
boj14891: 톱니바퀴  (1) 2025.06.01
boj21939: 문제 추천 시스템 Version 1  (1) 2025.05.15
boj13904: 과제  (2) 2025.05.15
Upperbound , Lowerbound  (1) 2025.04.18
'Algorithm/백준' 카테고리의 다른 글
  • 연산자 끼워넣기, 스타트와 링크
  • boj14891: 톱니바퀴
  • boj21939: 문제 추천 시스템 Version 1
  • boj13904: 과제
미네구스
미네구스
  • 미네구스
    망구스 blog
    미네구스
  • 전체
    오늘
    어제
    • 분류 전체보기 (174)
      • Kotlin (0)
      • 시큐리티 (0)
        • 개발자 유미 (0)
      • 배포 (4)
      • 회고 (0)
      • Algorithm (143)
        • 프로그래머스 코딩테스트 문제풀이전략 (37)
        • 백준 (66)
        • 프로그래머스 (18)
        • Leetcode (22)
        • 코테 팁 (0)
      • 프로젝트 (8)
        • WEPIK (3)
        • PICK-O (5)
      • CS (1)
        • 운영체제 (5)
        • 네트워크 (1)
        • 면접스터디 (2)
      • 면접 (0)
        • 코테후기 (0)
        • 면접후기 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    `
    백트래킹
    N과 M
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
미네구스
[백준] 감시
상단으로

티스토리툴바