https://www.acmicpc.net/problem/15683
처음 풀었던 전략 : 그리디
1. 각 카메라 위치를 리스트에 넣어두고
2. 카메라 하나씩 처리 -> 카메라 유형에 따라 가능한 경우의수중 사각지대를 제일 많이 없애는 방향 구하기
3. 카메라 감시 처리 -> 해당 방향으로 카메라가 감시한 영역을 -1로 설정
매 카메라마다 가장 많이 사각지대를 지우는 방향의 로직이었는데,
지금 카메라가 최적의 수를 포기하더라도 다음 카메라가 어떻게 잘 관제해주면 더 좋은 합이 나올 수 있었음 << 그래서 틀림
결국 모든 카메라 조합에 대해 완전탐색을 해야했고, << 카메라 개수가 8개까지 제한이 걸린거로 눈치를 챘을 수도 있을 것 같다.
시간 절약을 위해 백트래킹을 사용해야 하는 문제.
dfs로 1번카메라 방향설정 -> 2, 3, 4, 5, 6 설정후 마지막 카메라까지 설정했다면 해당 케이스의 사각지대 계산, 이후 return
그럼 마지막 카메라 경우 하나가 방향이 바뀐 케이스가 다음 케이스니까 사각지대 계산, 이후 return
이런 식으로 백트래킹을 하기 위해 매 dfs마다 board를 복사해서 각 케이스마다 다른 board를 사용하도록 해줘야한다. 그게 copyBoard 메서드다.
안그럼 다른케이스끼리 서로 같은 board 건드리고 난리난다. java에선 clone을 썼는데 파이썬이라면 어떻게 전달해야할까?
import java.io.*;
import java.util.*;
public class bj_15683_감시 {
static int n, m;
static int[][] board;
// 0 : 동 1 : 남 2 :서 3 : 북
static int[][][] mode = {
{},
{{0}, {1}, {2}, {3}},
{{0, 2}, {1, 3}},
{{0, 3}, {0, 1}, {1, 2}, {2, 3}},
{{0, 2, 3}, {0, 1, 3}, {0, 1, 2}, {1, 2, 3}},
{{0, 1, 2, 3}}
};
static int[] dr = {0, 1, 0, -1};
static int[] dc = {1, 0, -1, 0};
static List<int[]> camera;
static int answer = 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];
camera = new ArrayList<>();
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 && board[i][j] < 6){
camera.add(new int[] {i, j, board[i][j]});
}
}
}
dfs(0, board);
System.out.print(answer);
}
static void dfs(int index, int[][] prevBoard){
if (index == camera.size()){
answer = Math.min(answer, count_spot(prevBoard));
return;
}
int r = camera.get(index)[0];
int c = camera.get(index)[1];
int type = camera.get(index)[2];
for (int i = 0; i < mode[type].length; i++){
int[][] nextBoard = copyBoard(prevBoard);
for (int d : mode[type][i]){
fill(r, c, d, nextBoard);
}
dfs(index + 1, nextBoard);
}
}
static void fill(int r, int c, int direction, int[][] tempBoard){
int nr = r + dr[direction];
int nc = c + dc[direction];
while(0 <= nr && nr < n && 0 <= nc && nc < m && tempBoard[nr][nc] != 6){
if (tempBoard[nr][nc] == 0) tempBoard[nr][nc] = -1;
nr += dr[direction];
nc += dc[direction];
}
}
static int[][] copyBoard(int[][] original){
int[][] copy = new int[n][m];
for(int i = 0; i<n; i++){
copy[i] = original[i].clone();
}
return copy;
}
static int count_spot(int[][] tempBoard){
int count = 0;
for(int i = 0; i< n; i++){
for (int j = 0; j < m; j++)
if (tempBoard[i][j] == 0) count++;
}
return count;
}
}
구현 문제는 케이스 지킨다고 시간도 오래걸려서
열심히 풀었는데 처음부터 접근이 잘못된 경우일 때 너무 허무한 것 같다.
'알고리즘 풀이' 카테고리의 다른 글
| [백준] 2150 Strongly Connected Component (0) | 2026.01.12 |
|---|---|
| [백준] 2206 벽 부수고 이동하기 (Java) (0) | 2025.12.24 |
| [프로그래머스] Level 2. H-index (python) (2) | 2025.07.24 |
| [프로그래머스] (java) 타겟넘버 (BFS, DFS) (0) | 2025.03.15 |
| [프로그래머스] 크기가 작은 부분문자열 (java) (0) | 2025.03.06 |