Skip to content

Commit a2e34fd

Browse files
committed
[Gold III] Title: 감시, Time: 52 ms, Memory: 79512 KB -BaekjoonHub
1 parent 27b4f7b commit a2e34fd

2 files changed

Lines changed: 268 additions & 0 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# [Gold III] 감시 - 15683
2+
3+
[문제 링크](https://www.acmicpc.net/problem/15683)
4+
5+
### 성능 요약
6+
7+
메모리: 79512 KB, 시간: 52 ms
8+
9+
### 분류
10+
11+
구현, 브루트포스 알고리즘, 시뮬레이션, 백트래킹
12+
13+
### 제출 일자
14+
15+
2025년 8월 12일 16:32:23
16+
17+
### 문제 설명
18+
19+
<p>스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감시할 수 있는 방법은 다음과 같다.</p>
20+
21+
<table class="table table table-bordered" style="width: 100%;">
22+
<tbody>
23+
<tr>
24+
<td style="width: 20%; text-align: center; vertical-align: middle;"><img alt="" src="https://onlinejudgeimages.s3-ap-northeast-1.amazonaws.com/problem/15683/1.png" style="width: 113px; height: 70px;"></td>
25+
<td style="width: 20%; text-align: center;vertical-align: middle;"><img alt="" src="https://onlinejudgeimages.s3-ap-northeast-1.amazonaws.com/problem/15683/2.png" style="width: 156px; height: 70px;"></td>
26+
<td style="width: 20%; text-align: center;vertical-align: middle;"><img alt="" src="https://onlinejudgeimages.s3-ap-northeast-1.amazonaws.com/problem/15683/3.png" style="width: 100px; height: 100px;"></td>
27+
<td style="width: 20%; text-align: center;vertical-align: middle;"><img alt="" src="https://onlinejudgeimages.s3-ap-northeast-1.amazonaws.com/problem/15683/4.png" style="width: 138px; height: 100px;"></td>
28+
<td style="width: 20%; text-align: center;vertical-align: middle;"><img alt="" src="https://onlinejudgeimages.s3-ap-northeast-1.amazonaws.com/problem/15683/5.png" style="width: 149px; height: 150px;"></td>
29+
</tr>
30+
<tr>
31+
<td style="width: 20%; text-align: center;">1번</td>
32+
<td style="width: 20%; text-align: center;">2번</td>
33+
<td style="width: 20%; text-align: center;">3번</td>
34+
<td style="width: 20%; text-align: center;">4번</td>
35+
<td style="width: 20%; text-align: center;">5번</td>
36+
</tr>
37+
</tbody>
38+
</table>
39+
40+
<p>1번 CCTV는 한 쪽 방향만 감시할 수 있다. 2번과 3번은 두 방향을 감시할 수 있는데, 2번은 감시하는 방향이 서로 반대방향이어야 하고, 3번은 직각 방향이어야 한다. 4번은 세 방향, 5번은 네 방향을 감시할 수 있다.</p>
41+
42+
<p>CCTV는 감시할 수 있는 방향에 있는 칸 전체를 감시할 수 있다. 사무실에는 벽이 있는데, CCTV는 벽을 통과할 수 없다. CCTV가 감시할 수 없는 영역은 사각지대라고 한다.</p>
43+
44+
<p>CCTV는 회전시킬 수 있는데, 회전은 항상 90도 방향으로 해야 하며, 감시하려고 하는 방향이 가로 또는 세로 방향이어야 한다.</p>
45+
46+
<pre>0 0 0 0 0 0
47+
0 0 0 0 0 0
48+
0 0 1 0 6 0
49+
0 0 0 0 0 0</pre>
50+
51+
<p>지도에서 0은 빈 칸, 6은 벽, 1~5는 CCTV의 번호이다. 위의 예시에서 1번의 방향에 따라 감시할 수 있는 영역을 '<code>#</code>'로 나타내면 아래와 같다.</p>
52+
53+
<table class="table table table-bordered" style="width: 100%;">
54+
<tbody>
55+
<tr>
56+
<td style="width: 25%; text-align: center;">
57+
<pre>0 0 0 0 0 0
58+
0 0 0 0 0 0
59+
0 0 1 # 6 0
60+
0 0 0 0 0 0</pre>
61+
</td>
62+
<td style="width: 25%; text-align: center;">
63+
<pre>0 0 0 0 0 0
64+
0 0 0 0 0 0
65+
# # 1 0 6 0
66+
0 0 0 0 0 0</pre>
67+
</td>
68+
<td style="width: 25%; text-align: center;">
69+
<pre>0 0 # 0 0 0
70+
0 0 # 0 0 0
71+
0 0 1 0 6 0
72+
0 0 0 0 0 0</pre>
73+
</td>
74+
<td style="width: 25%; text-align: center;">
75+
<pre>0 0 0 0 0 0
76+
0 0 0 0 0 0
77+
0 0 1 0 6 0
78+
0 0 # 0 0 0</pre>
79+
</td>
80+
</tr>
81+
<tr>
82+
<td style="width: 25%; text-align: center;">→</td>
83+
<td style="width: 25%; text-align: center;">←</td>
84+
<td style="width: 25%; text-align: center;">↑</td>
85+
<td style="width: 25%; text-align: center;">↓</td>
86+
</tr>
87+
</tbody>
88+
</table>
89+
90+
<p>CCTV는 벽을 통과할 수 없기 때문에, 1번이 → 방향을 감시하고 있을 때는 6의 오른쪽에 있는 칸을 감시할 수 없다.</p>
91+
92+
<pre>0 0 0 0 0 0
93+
0 2 0 0 0 0
94+
0 0 0 0 6 0
95+
0 6 0 0 2 0
96+
0 0 0 0 0 0
97+
0 0 0 0 0 5</pre>
98+
99+
<p>위의 예시에서 감시할 수 있는 방향을 알아보면 아래와 같다.</p>
100+
101+
<table class="table table table-bordered" style="width: 100%;">
102+
<tbody>
103+
<tr>
104+
<td style="width: 25%; text-align: center;">
105+
<pre>0 0 0 0 0 #
106+
# 2 # # # #
107+
0 0 0 0 6 #
108+
0 6 # # 2 #
109+
0 0 0 0 0 #
110+
# # # # # 5</pre>
111+
</td>
112+
<td style="width: 25%; text-align: center;">
113+
<pre>0 0 0 0 0 #
114+
# 2 # # # #
115+
0 0 0 0 6 #
116+
0 6 0 0 2 #
117+
0 0 0 0 # #
118+
# # # # # 5</pre>
119+
</td>
120+
<td style="width: 25%; text-align: center;">
121+
<pre>0 # 0 0 0 #
122+
0 2 0 0 0 #
123+
0 # 0 0 6 #
124+
0 6 # # 2 #
125+
0 0 0 0 0 #
126+
# # # # # 5</pre>
127+
</td>
128+
<td style="width: 25%; text-align: center;">
129+
<pre>0 # 0 0 0 #
130+
0 2 0 0 0 #
131+
0 # 0 0 6 #
132+
0 6 0 0 2 #
133+
0 0 0 0 # #
134+
# # # # # 5</pre>
135+
</td>
136+
</tr>
137+
<tr>
138+
<td style="width: 25%; text-align: center;">왼쪽 상단 2: ↔, 오른쪽 하단 2: ↔</td>
139+
<td style="width: 25%; text-align: center;">왼쪽 상단 2: ↔, 오른쪽 하단 2: ↕</td>
140+
<td style="width: 25%; text-align: center;">왼쪽 상단 2: ↕, 오른쪽 하단 2: ↔</td>
141+
<td style="width: 25%; text-align: center;">왼쪽 상단 2: ↕, 오른쪽 하단 2: ↕</td>
142+
</tr>
143+
</tbody>
144+
</table>
145+
146+
<p>CCTV는 CCTV를 통과할 수 있다. 아래 예시를 보자.</p>
147+
148+
<pre>0 0 2 0 3
149+
0 6 0 0 0
150+
0 0 6 6 0
151+
0 0 0 0 0
152+
</pre>
153+
154+
<p>위와 같은 경우에 2의 방향이 ↕ 3의 방향이 ←와 ↓인 경우 감시받는 영역은 다음과 같다.</p>
155+
156+
<pre># # 2 # 3
157+
0 6 # 0 #
158+
0 0 6 6 #
159+
0 0 0 0 #
160+
</pre>
161+
162+
<p>사무실의 크기와 상태, 그리고 CCTV의 정보가 주어졌을 때, CCTV의 방향을 적절히 정해서, 사각 지대의 최소 크기를 구하는 프로그램을 작성하시오.</p>
163+
164+
### 입력
165+
166+
<p>첫째 줄에 사무실의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 8)</p>
167+
168+
<p>둘째 줄부터 N개의 줄에는 사무실 각 칸의 정보가 주어진다. 0은 빈 칸, 6은 벽, 1~5는 CCTV를 나타내고, 문제에서 설명한 CCTV의 종류이다. </p>
169+
170+
<p>CCTV의 최대 개수는 8개를 넘지 않는다.</p>
171+
172+
### 출력
173+
174+
<p>첫째 줄에 사각 지대의 최소 크기를 출력한다.</p>
175+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import Foundation
2+
3+
typealias Tuple = (Int, Int, Int)
4+
let dx = [-1, 0, 1, 0]
5+
let dy = [0, 1, 0, -1]
6+
7+
8+
let nm = readLine()!.components(separatedBy:" ").map{Int($0)!}
9+
let N = nm[0], M = nm[1] // x, y좌표
10+
var arr = [[Int]]()
11+
var cctvList = [Tuple]() // cctv를 담고있는 배열
12+
var zeroCnt = 0 // 처음 0의 숫자
13+
let posXRange = 0..<N
14+
let posYRange = 0..<M
15+
16+
for _ in 0..<N {
17+
arr.append(readLine()!.components(separatedBy:" ").map{Int($0)!})
18+
}
19+
20+
for i in arr.indices {
21+
for j in arr[i].indices {
22+
if arr[i][j] >= 1 && arr[i][j] <= 5 { // cctv들은 cctv배열에 추가
23+
cctvList.append((arr[i][j], i, j))
24+
} else if arr[i][j] == 0 {
25+
zeroCnt += 1
26+
}
27+
}
28+
}
29+
30+
// 한 줄을 방향에 맞게 처리하는 함수
31+
func coverZeroOneline(_ pos: (Int, Int), _ dir: (Int), _ tmpArr: inout [[Int]]) -> Int {
32+
var posX = pos.0 + dx[dir]
33+
var posY = pos.1 + dy[dir]
34+
var coverZeroCnt = 0
35+
while posXRange ~= posX && posYRange ~= posY && tmpArr[posX][posY] != 6 {
36+
if tmpArr[posX][posY] == 0 {
37+
tmpArr[posX][posY] = -1
38+
coverZeroCnt += 1
39+
}
40+
posX = posX + dx[dir]
41+
posY = posY + dy[dir]
42+
}
43+
return coverZeroCnt
44+
}
45+
46+
// cctv타입에 따라 라인을 처리하는 ㅎ마수
47+
func runCCTV(_ cctvType: Int, _ cctvPos: (Int, Int), _ dir: Int, _ tmpArr: inout [[Int]]) -> Int {
48+
var coverToCnt = 0
49+
if cctvType == 1 {
50+
coverToCnt += coverZeroOneline(cctvPos, dir, &tmpArr)
51+
} else if cctvType == 2 {
52+
[0, 2].forEach { dirCnt in
53+
coverToCnt += coverZeroOneline(cctvPos, (dir + dirCnt) % 4, &tmpArr)
54+
}
55+
} else if cctvType == 3 {
56+
(0...1).forEach { dirCnt in
57+
coverToCnt += coverZeroOneline(cctvPos, (dir + dirCnt) % 4, &tmpArr)
58+
}
59+
} else if cctvType == 4 {
60+
(0...2).forEach { dirCnt in
61+
coverToCnt += coverZeroOneline(cctvPos, (dir + dirCnt) % 4, &tmpArr)
62+
}
63+
} else if cctvType == 5 {
64+
(0...3).forEach { dirCnt in
65+
coverToCnt += coverZeroOneline(cctvPos, (dir + dirCnt) % 4, &tmpArr)
66+
}
67+
}
68+
return coverToCnt
69+
}
70+
71+
var Ans = Int.max
72+
func DFS(_ cctvIdx: Int, _ coverCnt: Int, _ arr: [[Int]]) {
73+
if cctvIdx >= cctvList.count {
74+
let temp = zeroCnt - coverCnt
75+
Ans = Ans > temp ? temp : Ans // 현재 커버한게 더 많다면 temp가 적어지므로 적은 값이 Ans가 된다.
76+
return
77+
}
78+
79+
let newCCTV = cctvList[cctvIdx]
80+
var tmpArr = arr
81+
for dir in 0..<4 {
82+
let cctvType = newCCTV.0
83+
let cctvPos = (newCCTV.1, newCCTV.2)
84+
85+
let newCoverCnt = runCCTV(cctvType, cctvPos, dir, &tmpArr)
86+
DFS(cctvIdx+1, coverCnt + newCoverCnt, tmpArr)
87+
tmpArr = arr
88+
}
89+
90+
}
91+
92+
DFS(0, 0, arr)
93+
print(Ans)

0 commit comments

Comments
 (0)