[백준 15683] 감시(Java)

최민길(Gale)·2023년 1월 23일
1

알고리즘

목록 보기
21/172

문제 링크 : https://www.acmicpc.net/problem/15683

이 문제는 백트래킹을 이용하여 문제의 조건대로 하나하나 구현해나가면 풀 수 있습니다.

이 문제의 접근 방식은 단순합니다. 각 CCTV 타입 별로 칸을 하나하나씩 읽어나가면서 감지 가능 칸을 체크한 후 체크되어있지 않는 부분을 카운트해서 출력하면 됩니다.

여기서 주의할 점은 체크하는 방법입니다. 만약 두 개의 CCTV가 같은 곳을 감지하고 있다면 한 CCTV가 각도를 변경했을 경우 다른 CCTV가 여전히 감지하고 있기 때문에 감지 범위 내입니다. 따라서 단순이 true false로 처리하면 이 부분이 제대로 카운트되지 않기 때문에 CCTV가 감지할 때마다 감지 카운트를 1씩 증가시켜 감지 카운트가 0일 경우 false로서 처리하는 방식으로 진행하시면 되겠습니다.

다음은 코드입니다.

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

public class Main{

    static int N,M;
    static int[][] req = new int[9][9];
    static int[][] check = new int[9][9];
    static int res = 81;
    static ArrayList<Pair> cctvList = new ArrayList<>();
    static int[] dx = {0,1,0,-1};
    static int[] dy = {1,0,-1,0};

    static int voidNum(){
        int ans = 0;
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                if(check[i][j]==0) ans++;
            }
        }
        return ans;
    }

    static void move(int y, int x, int dir, boolean isCheck){
        int ny = y;
        int nx = x;

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

            if(nx<0 || nx>=M || ny<0 || ny>=N) break;
            if(req[ny][nx] == 6) break;

            if(isCheck) check[ny][nx]++;
            else{
                if(check[ny][nx]>0) check[ny][nx]--;
            }
        }
    }

    static void backtracking(int cnt){
        if(cnt == cctvList.size()){
            int ans = voidNum();
            if(res > ans) res = ans;
            return;
        }

        int y = cctvList.get(cnt).y;
        int x = cctvList.get(cnt).x;

        switch (req[y][x]){
            case 1:
                for(int dir=0;dir<4;dir++){
                    move(y,x,dir,true);
                    backtracking(cnt+1);
                    move(y,x,dir,false);
                }
                break;
            case 2:
                for(int dir=0;dir<2;dir++){
                    move(y,x,dir,true);
                    move(y,x,dir+2,true);
                    backtracking(cnt+1);
                    move(y,x,dir,false);
                    move(y,x,dir+2,false);
                }
                break;
            case 3:
                for(int dir=0;dir<4;dir++){
                    int newDir = dir+1;
                    if(newDir==4) newDir = 0;
                    move(y,x,dir,true);
                    move(y,x,newDir,true);
                    backtracking(cnt+1);
                    move(y,x,dir,false);
                    move(y,x,newDir,false);
                }
                break;
            case 4:
                move(y,x,0,true);
                move(y,x,1,true);
                move(y,x,2,true);
                move(y,x,3,true);
                for(int dir=0;dir<4;dir++){
                    move(y,x,dir,false);
                    backtracking(cnt+1);
                    move(y,x,dir,true);
                }
                move(y,x,0,false);
                move(y,x,1,false);
                move(y,x,2,false);
                move(y,x,3,false);
                break;
            case 5:
                move(y,x,0,true);
                move(y,x,1,true);
                move(y,x,2,true);
                move(y,x,3,true);
                backtracking(cnt+1);
                move(y,x,0,false);
                move(y,x,1,false);
                move(y,x,2,false);
                move(y,x,3,false);
                break;
        }
    }

    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());

        for(int i=0;i<N;i++){
            st = new StringTokenizer(br.readLine());
            for(int j=0;j<M;j++){
                req[i][j] = Integer.parseInt(st.nextToken());
                if(req[i][j] != 0 && req[i][j] != 6){
                    cctvList.add(new Pair(i,j));
                    check[i][j] = 81;
                }
                else if(req[i][j] == 6) check[i][j] = 81;
            }
        }
        backtracking(0);
        System.out.println(res);
    }
}

class Pair{
    int y;
    int x;

    public Pair(int y, int x){
        this.y = y;
        this.x = x;
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글