일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- DFS
- testdb
- boj10775
- onTouchListner
- boj15998
- boj2239
- boj15654
- backtracking
- boj7579
- django
- onTouch
- nestedjson
- boj_15684
- 동적계획법
- Spring
- boj15683
- boj_15685
- boj2252
- DynamicProgramming
- mysql
- bruteforce
- DP
- boj10942
- BOJ
- TDD
- react
- BFS
- boj15954
- springboot
- euclideanalgorithm
- Today
- Total
이마닷의 블로그
[BOJ] 15683:감시 본문

0. 문제
https://www.acmicpc.net/problem/15683
15683번: 감시
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감
www.acmicpc.net
1. 문제분석
- 8개 이하의 cctv들이 만들어낼 수 있는 사각지대의 넓이를 구하기 위해서는, 각 cctv들이 감시할 수 있는 경우의 수를 모두 고려해 보아야 한다. 즉, 각 cctv들이 움직일 수 있는 경우의 수 대로 사각지대 넓이를 각각 구해보고 그 최솟값을 구해야 하므로, cctv들이 감시할 수 있는 영역을 순차적으로 대입시켜보고, 다시 원래 상태로 복구한 뒤에 새로운 경우의 수를 대입시키는 방식으로 코드를 작성해야 한다. 따라서 n-queen 문제를 푸는 것과 마찬가지로 백트래킹(backtracking)을 사용해 문제를 풀어야 한다.
2. 주의할 점
- 백트래킹 시, 감시가 이루어진 위치가 여러 개의 cctv에 의해서 여러 번의 감시가 이루어질 수 있음에 유의해야 한다. 즉, 하나의 경우의 수일 때 결과를 확인한 뒤, 다음 경우의 수를 대입시키기 위해 그리드(2차원 배열)를 원상복구 시킬 때에 있어서, 해당 위치가 반드시 지금의 경우의 수를 대입한 결과에 의해서만 감시되지는 않았음을 확인해야 한다.
3. 소스코드(Java)
// boj 15683 감시
// backtracking
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.Vector;
public class boj_15683 {
static int n,m;
static int[][] grid;
static int ans = 987654321;
static int [][] cams;
static final int[][][][] cctv = {
{},
{
{{-1,0}},
{{0,1}},
{{1,0}},
{{0,-1}}
},
{
{{-1,0},{1,0}},
{{0,1},{0,-1}}
},
{
{{-1,0},{0,1}},
{{0,1},{1,0}},
{{1,0},{0,-1}},
{{0,-1},{-1,0}}
},
{
{{0,-1},{-1,0},{0,1}},
{{-1,0},{0,1},{1,0}},
{{0,1},{1,0},{0,-1}},
{{1,0},{0,-1},{-1,0}}
},
{
{{-1,0},{0,1},{1,0},{0,-1}}
}
};
static final int BLANK = 0;
static final int WALL = 6;
static final int SHADE = 7;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = stoi(st.nextToken());
m = stoi(st.nextToken());
grid = new int[n][m];
Vector<int[]> tmpCams = new Vector<>();
for (int i = 0; i < n; ++i) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < m; ++j) {
grid[i][j] = stoi(st.nextToken());
if (1 <= grid[i][j] && grid[i][j] <= 5) tmpCams.add(new int[]{i, j});
}
}
cams = tmpCams.toArray(new int[tmpCams.size()][2]);
go(0);
System.out.print(ans);
}
public static int stoi(String s) {return Integer.parseInt(s);}
public static void go(int camIdx) {
if (camIdx == cams.length) {
int blankCnt = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j)
if (grid[i][j] == BLANK) blankCnt++;
}
if (blankCnt < ans) ans = blankCnt;
return;
}
int nowCctv = grid[cams[camIdx][0]][cams[camIdx][1]];
for (int[][] dirs: cctv[nowCctv]) {
draw(cams[camIdx][0], cams[camIdx][1], SHADE, dirs);
go(camIdx + 1);
draw(cams[camIdx][0], cams[camIdx][1], -SHADE, dirs);
}
}
public static void draw(int r, int c, int toDraw, int[][] dirs) {
for (int[] dir: dirs) {
int nr = r + dir[0];
int nc = c + dir[1];
while (nr >= 0 && nr < n && nc >= 0 && nc < m) {
if (grid[nr][nc] == WALL) break;
if (grid[nr][nc] == BLANK || grid[nr][nc] >= SHADE)
// 단순히 감시의 유무만 확인하지 말고, 몇 번의 감시가 누적되는지 확인!!
grid[nr][nc] += toDraw;
nr += dir[0];
nc += dir[1];
}
}
}
}
4. 여담
- 파이팅!
'problem-solving' 카테고리의 다른 글
[BOJ] 15685:드래곤 커브 (0) | 2021.04.10 |
---|---|
[BOJ] 15684:사다리조작 (0) | 2021.04.07 |
[BOJ] 15998:카카오머니 (0) | 2021.01.11 |
[BOJ] 15954:인형들 (0) | 2021.01.11 |
[BOJ] 2252:줄세우기 (0) | 2021.01.03 |