문제
기록 포인트
- 시작점이 여러 개인 너비 우선 탐색(BFS)
- BFS의 탐색 순서를 관리하는 frontier에 여러 개의 시작점을 넣고 시작하면 됨
- 어떻게 보면, 하나의 시작점으로 BFS를 진행하는 중간부터 시작한다고 볼 수 있음
- 매트릭스에서 상하좌우 탐색하는 방법
- 좌표(x,y)의 상하좌우 좌표로 이동하는 delta값을 이용해 찾기
- 이 문제에서는 3차원을 탐색하여 6개 위치를 탐색하며 원리는 동일
dxs=[-1,1,0,0]
dys=[0,0,-1,1]
for dx,dy in zip(dxs, dys):
x2, y2 = x1+dx, y1+dy
if x2 < 0 or x2 >= len(matrix) or y2 < 0 or y2 >= len(matrix):
continue
- 각 위치의 탐색 시점을 기록하는 방법 (시작점과의 최소 거리를 기록하는 방법)
- 매트릭스 상에서 탐색을 진행하므로 매트릭스 좌표(U) 상에 탐색 시점(t)을 기록
- 해당 좌표(U)의 인접 리스트를 통해 탐색된 다음 좌표(V)는 탐색 시점이 t+1이 됨
접근 방식
제출 답안
import sys
from collections import deque
M, N, H = tuple(map(int, sys.stdin.readline().split()))
matrix = []
frontier = []
goal_count = 0
for h in range(H):
space = []
for x in range(N):
row = list(map(int, sys.stdin.readline().split()))
space.append(row)
for y in range(M):
if row[y] == 1:
frontier.append((h, x, y))
elif row[y] == 0:
goal_count += 1
matrix.append(space)
def BFS(matrix, frontier):
search_count = 0
if goal_count == 0:
return search_count
max_time = 0
dhs = [0,0,0,0,-1,1]
dxs = [-1,1,0,0,0,0]
dys = [0,0,-1,1,0,0]
frontier = deque(frontier)
while frontier:
v1 = frontier.popleft()
v1_h, v1_x, v1_y = v1
v1_time = matrix[v1_h][v1_x][v1_y]
for dh, dx, dy in zip(dhs, dxs, dys):
h = v1_h + dh
x = v1_x + dx
y = v1_y + dy
if h < 0 or h >= H or x < 0 or x >= N or y < 0 or y >= M:
continue
if matrix[h][x][y] != 0:
continue
search_count += 1
matrix[h][x][y] = v1_time + 1
if max_time < v1_time:
max_time = v1_time
frontier.append((h, x, y))
if search_count == goal_count:
return max_time
else:
return -1
print(BFS(matrix, frontier))