알고리즘/BAEKJOON (Python)
[ 백준 ][ 골드3 ] 163236번 - 아기 상어 ( 파이썬 Python )
Heeto
2023. 3. 27. 16:46
링크 : https://www.acmicpc.net/problem/16236
16236번: 아기 상어
N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가
www.acmicpc.net
코드
from collections import deque
n = int(input())
sx,sy = -1,-1
graph = []
eat_cnt, fish_cnt, time, size = 0, 0, 0, 2
dx,dy = [-1,0,0,1],[0,-1,1,0]
for i in range(n):
l = list(map(int,input().split()))
for j in range(n):
if l[j] == 9:
sx,sy = i,j
elif l[j] > 0:
fish_cnt += 1
graph.append(l)
graph[sx][sy] = 0
def BFS(x,y):
Q = deque([(x,y,0)])
dist_list = []
visit = [[False] * n for _ in range(n)]
visit[x][y] = True
min_dist = 1e9
while Q:
x,y,dist = Q.popleft()
for i in range(4):
nx,ny = x+dx[i],y+dy[i]
if 0 <= nx < n and 0 <= ny < n and not visit[nx][ny]:
if graph[nx][ny] <= size:
visit[nx][ny] = True
if 0 < graph[nx][ny] < size:
min_dist = dist
dist_list.append((dist+1,nx,ny))
elif dist+1 <= min_dist:
Q.append((nx,ny,dist+1))
return sorted(dist_list)[0] if dist_list else False
while fish_cnt:
res = BFS(sx,sy)
if not res:
break
sx,sy = res[1],res[2]
graph[sx][sy] = 0
time += res[0]
eat_cnt += 1
fish_cnt -= 1
if size == eat_cnt:
size += 1
eat_cnt = 0
print(time)
풀이
처음에는 한 번의 BFS안에서 모든 물고기를 찾아내고 싶었다. 탐색하는 방향을 위, 왼쪽, 오른쪽, 아래 순으로 설정하게 되면 먼저 탐색하는 방향이 문제에서 제시한 조건과 일치하기 때문에 정답을 구할 수 있을 것 같았다.
하지만 이렇게 하면 방문처리를 하기가 애매했다. 상황에따라 어떤 칸은 방문했더라도 또 방문하게 되는데 이 방문처리를 해결할 방법이 없었다.
따라서 한 번의 BFS에서는 해결할 수 없다고 생각했고 한 번 BFS할 때마다 가장 가까운 물고기 한 마리를 찾는 방식으로 변경했다.
BFS의 특성상 처음 방문한 노드는 그 당시가 최단거리이다. 위치를 옮길 때마다 BFS로 모든 물고기의 최단거리를 계산한 후 그 중 조건에 맞는 가장 가까운 물고기로 이동한다. 이동한 후에는 그 칸을 0으로 바꿔주고 내가 앞으로 찾을 수 있는 물고기의 개수도 바꿔준다.
만약 앞으로 이동할 수 있는 물고기칸이 없다면 지금까지의 시간을 출력한다.