문제
문제 링크 : https://www.acmicpc.net/problem/15683
15683번: 감시
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감
www.acmicpc.net
CODE
import sys
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
camdir = [0, 4, 2, 4, 4, 1] # 카메라 종류별 분별 가능한 방향 수
def watch(idx, dir, office):
if cam[idx][2] == 1:
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir], y + dy[dir]
elif cam[idx][2] == 2:
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir], y + dy[dir]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir + 2], y + dy[dir + 2]
elif cam[idx][2] == 3:
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir - 1], y + dy[dir - 1]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir], y + dy[dir]
elif cam[idx][2] == 4:
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir - 2], y + dy[dir - 2]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir - 1], y + dy[dir - 1]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir], y + dy[dir]
elif cam[idx][2] == 5:
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir], y + dy[dir]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir + 1], y + dy[dir + 1]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir + 2], y + dy[dir + 2]
x, y = cam[idx][0], cam[idx][1]
while 0 <= x < n and 0 <= y < m and office[x][y] != 6:
if office[x][y] == 0:
office[x][y] = 7
x, y = x + dx[dir + 3], y + dy[dir + 3]
def solve(cnt, off):
global result
if cnt == len(cam):
temp = 0
for i in range(n):
temp += off[i].count(0)
result = min(result, temp)
return
for i in range(camdir[cam[cnt][2]]):
t_off = [item[:] for item in off]
watch(cnt, i, t_off)
solve(cnt + 1, t_off)
n, m = map(int, sys.stdin.readline().split())
office = [list(map(int, sys.stdin.readline().split())) for _ in range(n)]
result = n * m
cam = [] # 카메라 위치 저장
for i in range(n):
for j in range(m):
if 0 < office[i][j] < 6:
cam.append([i, j, office[i][j]])
solve(0, office)
print(result)
풀이
💡 idea
- DFS로 풀어 모든 경우를 탐색하자!
- 각 카메라가 감시하는 곳을 모두 표시한다
- 카메라 종류별로 분별 가능한 방향 수는 다음과 같다
1) 4가지
2) 2가지
3) 4가지
4) 4가지
5) 1가지
💡 implementation
camdir = [0, 4, 2, 4, 4, 1]
- 카메라 종류별로 분별 가능한 방향 수
cam = []
for i in range(n):
for j in range(m):
if 0 < office[i][j] < 6:
cam.append([i, j, office[i][j]])
- 카메라의 위치와 종류를 리스트 cam에 따로 저장하여 관리한다
- solve 함수 : DFS
- watch 함수 : 카메라가 감시하는 구역의 표시
t_off = [item[:] for item in off]
- copy.deepcopy()를 이용하여 깊은 복사를 하는 것보다 slicing하는 것이 훨씬 빠르다!
- deepcopy()를 사용한 코드는 3956ms → slicing을 통한 깊은 복사를 한 코드 548ms
📌 속도 차이에 충격 받고 파이썬에서 복사의 종류와 시간에 대해서 글로 정리했습니다!
https://codesyun.tistory.com/198
[Python] 파이썬 리스트 복사 : 시간 초과 해결, 깊은 복사와 얕은 복사, copy, deepcopy, slicing, 2차원 리
더보기 백준 풀이를 하다 리스트를 깊은 복사할 때, deepcopy()를 사용한 코드가 slicing을 사용한 코드보다 7배 이상의 시간이 걸린 것을 확인하고 정리해봐야겠다는 생각이 들었습니다! 가뜩이나
codesyun.tistory.com
결과
'Baekjoon' 카테고리의 다른 글
[BOJ / 백준] 1303번 전쟁 - 전투 파이썬 (Python) 문제 풀이 (0) | 2021.10.06 |
---|---|
[BOJ / 백준] 1260번 DFS와 BFS 파이썬(Python) 문제 풀이 (0) | 2021.10.06 |
[BOJ / 백준] 16637번 괄호 추가하기 파이썬(Python) 문제 풀이 (0) | 2021.08.04 |
[BOJ / 백준] 17088번 등차수열 변환 파이썬(Python) 문제 풀이 (0) | 2021.08.03 |
[BOJ / 백준] 17089번 세 친구 성공 파이썬(Python) 문제 풀이 (0) | 2021.08.02 |