Hansel

백준_15683(DFS) 본문

알고리즘과 자료구조/BFS&DFS

백준_15683(DFS)

핑슬 2022. 4. 3. 15:49

각 cctv마다 탐색할 수 있는 방향을 전부 돌려본 후 cctv가 탐지하지 못하는 위치의 수 중 최소값을 찾아내는 문제이다.

 

우선 cctv의 좌표를 담은 List에서 하나씩 빼온 후 해당 cctv 타입에 맞게 방향을 전부 탐색하게 한다

1번의 탐색이 일어날 때 마다 탐색을 했던 맵을 다음 cctv로 보내주면서 재귀식으로 전부 탐색하게 하면 된다.

 

 

package TT4_APR;

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

public class Boj_15683 {
    static int N, M;
    static int[][] arr;

    public static class Point {
        int y;
        int x;
        int type;
        public Point(int y, int x,int type) {
            this.y = y;
            this.x = x;
            this.type = type;
        }
    }

    static ArrayList<Point> al = new ArrayList<>();

    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()); //열
        arr = 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++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
                if (arr[i][j] != 0 && arr[i][j] != 6) { //cctv의 좌표
                    al.add(new Point(i,j, arr[i][j]));
                }
            }
        }
        dfs(0, arr);
        System.out.println(result);
    }
    // 1번 => 한방향 , 회전 4번 (동서남북)
    // 2번 => 양방향, 회전 2번 (위, 옆)
    // 3번 => 직각 , 회전 4번 (우측 위아래, 좌측 위아래)
    // 4번 => 3방향, 회전 4번 (직선 좌우, 수평 위아래)
    // 5번 => 전방향, 1번
    // + cctv는 cctv를 통과할 수 있다.

    //각 번호에 맞는 회전 식이 필요함.

    //차례대로 뽑아서 돌려보고 돌린 맵을 다음 번호의 cctv로 보냄 -> 반복복

    static int result = 64;
   private static void dfs(int idx,int[][] map) {
        if(idx==al.size()){ //모든 cctv 다 돌아봤으면
            int cnt =0;
            for(int i=1;i<=N;i++){
                for(int j=1;j<=M;j++){
                    if(map[i][j]==0) cnt++;
                }
            }
            result= Math.min(result,cnt);

            for(int i=1;i<=N;i++){
                for(int j=1;j<=M;j++){
                    System.out.print(map[i][j] + " ");
                }
                System.out.println();
            }
            System.out.println("result = " +  result);
            return;
        }
        else{
            //cctv 뽑아서 돌려보고 돌린 맵을 다음 cctv한테 보내줌(재귀식으로)
            Point point = al.get(idx);
            switch (point.type) {
                case 1:
                    //한 방향으로 쭉
                    for(int i=0;i<4;i++){
                        int[][] copied = copied(map);
                        direction(copied,point.y,point.x,i);
                        dfs(idx+1,copied);

                    }
                    break;
                case 2:
                    for(int i=0;i<2;i++){
                        int[][] copied = copied(map);
                        direction(copied,point.y,point.x,i);
                        direction(copied,point.y,point.x,i+2);
                        dfs(idx+1,copied);
                    }
                    break;
                case 3:
                    for(int i=0;i<4;i++){
                        int[][] copied = copied(map);
                        direction(copied,point.y,point.x,i);
                        direction(copied,point.y,point.x,(i+1)%4);
                        dfs(idx+1,copied);
                    }
                    break;
                case 4:
                    for(int i=0;i<4;i++){
                        int[][] copied = copied(map);
                        direction(copied,point.y,point.x,i);
                        direction(copied,point.y,point.x,(i+1)%4);
                        direction(copied,point.y,point.x,(i+2)%4);
                        dfs(idx+1,copied);
                    }
                    break;
                case 5:
                    int[][] copied = copied(map);
                    direction(copied,point.y,point.x,0);
                    direction(copied,point.y,point.x,1);
                    direction(copied,point.y,point.x,2);
                    direction(copied,point.y,point.x,3);
                    dfs(idx+1,copied);
                    break;
            }
        }
    }

    private static int[][] copied(int[][] map) {
       int[][] copied = new int[N+1][M+1];
       for(int i=1;i<=N;i++){
           for(int j=1;j<=M;j++){
               copied[i][j] = map[i][j];
           }
       }
       return copied;
    }

    private static void direction(int[][] copied, int y, int x, int dir) {
        if(dir==0){ //북쪽으로 전진
            for(int i=y;i>0;i--){
                if(copied[i][x]==6) break;
                else if(copied[i][x]==0) copied[i][x]=9;
            }
        }
        else if(dir==1){ //서쪽
            for(int i=x;i>0;i--){
                if(copied[y][i]==6) break;
                else if(copied[y][i]==0) copied[y][i]=9;
            }
        }
        else if(dir==2){//남쪽
            for(int i=y;i<=N;i++){
                if(copied[i][x]==6) break;
                else if(copied[i][x]==0) copied[i][x]=9;
            }
        }
        else if(dir==3){ //동쪽
            for(int i=x;i<=M;i++){
                if(copied[y][i]==6)break;
                else if(copied[y][i]==0) copied[y][i]=9;
            }
        }
    }

}

 

'알고리즘과 자료구조 > BFS&DFS' 카테고리의 다른 글

프로그래머스_카카오 프렌즈 컬러링북(DFS)  (0) 2022.05.06
백준_2573(DFS & BFS)  (0) 2022.04.07
백준_16236(BFS)  (0) 2022.03.15
백준_15666(DFS)  (0) 2022.03.09
백준_15657(DFS)  (0) 2022.03.09