개발/algorithm

[백준 15683번] 감시 - python

zzi_on2 2022. 2. 25. 15:12

문제 링크

https://www.acmicpc.net/problem/15683

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감

www.acmicpc.net

풀이

- dfs + 구현 문제 

cctv[] : cctv의 종류와 위치 저장 

mode[] : cctv 종류 별 바라볼 수 있는 방향 저장 

0 : 위쪽, 1 : 왼쪽, 2 : 아래쪽, 3 : 오른쪽 

import copy

dx = [ -1, 0, 1, 0 ]
dy = [ 0, -1, 0, 1 ]

INF = int(1e9)
# cctv 별 바라볼 수 있는 방향  
mode = [
  [],
  [[0],[1],[2],[3]],
  [ [1,3], [0,2]],
  [ [0,3], [2,3], [1,2], [0,1] ],
  [ [0,1,2], [1,2,3], [0,2,3], [0,1,3]],
  [ [0,1,2,3]]
]

# 감시할 수 있는 곳 7로 변환하는 함수 
def check(board, dir, x, y):
  for i in dir:
    nx = x
    ny = y

    while True:
      nx += dx[i]
      ny += dy[i]
      # 범위에서 벗어나거나 벽을 만나면 중단 
      if nx < 0 or ny < 0 or nx >= n or ny >= m:
        break
      if board[nx][ny] == 6:
        break
      # 7로 변환 
      if board[nx][ny] == 0:
        board[nx][ny] = 7 
        
def dfs(cnt,arr):
  global answer 

  # 모든 cctv의 감시할 수 있는 곳을 검사했으면 
  if cnt == len(cctv):
    count = 0 
    # 남은 0의 개수 계산 
    for i in range(n):
      count += arr[i].count(0)
    
    # 최솟값 갱신 
    answer = min(answer,count)
    return 
  
  # 그래프 복사 
  tmp = copy.deepcopy(arr)
  # cctv 종류와 위치 
  cctv_num, x, y = cctv[cnt]
  
  # cctv가 모든 바라볼 수 있는 방향에 대하여 
  for i in mode[cctv_num]:
    check(tmp,i,x,y)
    dfs(cnt+1, tmp)
    tmp = copy.deepcopy(arr)
    
n, m = map(int,input().split())

graph = []

for _ in range(n):
  graph.append(list(map(int,input().split())))

cctv = []
for i in range(n):
  for j in range(m):
    # cctv 종류와 위치 저장 
    if graph[i][j] != 0 and graph[i][j] != 6:
      cctv.append((graph[i][j],i,j))

answer = INF
dfs(0,graph)
print(answer)