BOJ 16236 아기 상어
접근 방법
BFS를 통해서 제일 가까운 물고기를 먹으면서 진행하면 된다고 생각했다. N<=20이라 BFS를 20번 한다고 해도 $\ 20^3 $이라 조건을 만족시키게 BFS를 편하게 반복해도 된다고 생각했다.
우선 상어의 좌표 (시작점)과 총 물고기의 개수를 받아야 한다고 생각했다. 문제 조건에서 물고기의 개수가 0일 때 상황을 종료해도 된다고 해서 이 값을 갖고 있어야 한다고 생각했다.
bfs를 통해서 현재 좌표에서 먹을 수 있는 물고기들을 구해서 list로 반환하였다. 동일한 크기를 가진 물고기가 존재할 경우에 문제에서 제시한 기준대로 정렬하여 조건을 제일 만족하는 물고기만 먹게 했다.
정답 코드
import sys
from collections import deque
input = sys.stdin.readline
n = int(input())
maps = []
for _ in range(n):
maps.append(list(map(int, input().split())))
shark_h, shark_w = 0,0
fishes = 0
for i in range(n):
for j in range(n):
if maps[i][j] == 9:
shark_h, shark_w = i,j
elif 0<maps[i][j] < 9:
fishes += 1
"""
bfs를 통해 현재 먹을 수 있는 물고기들을 다 구함
물고기들 중에서 조건에 적합한 물고기를 먹고 그 좌표로 이동
이를 fishes 수가 0이거나 크기가 모두 자기보다 크거나 같을 경우일때 멈춤
"""
moves = ([-1,0], [1,0], [0,1], [0,-1])
def bfs(start_h, start_w, size):
avails = []
q = deque()
q.append((start_h, start_w,0))
visited = set()
visited.add((start_h, start_w))
while q:
h,w,d = q.popleft()
for dh, dw in moves:
new_h, new_w, new_d = h+dh, w+dw, d+1
if 0<=new_h<n and 0<=new_w<n and (new_h, new_w) not in visited and maps[new_h][new_w] <= size:
q.append((new_h, new_w, new_d))
visited.add((new_h, new_w))
#먹을 수 있는 물고기 배열에 추가
if 0 < maps[new_h][new_w] < size:
avails.append((new_h, new_w, new_d))
avails.sort(key = lambda x: (x[2], x[0], x[1]))
return deque(avails)
size = 2
cnt = 0 #크기가 변할 때마다 초기화되는 물고기 수
total_time = 0
while True:
fish = bfs(shark_h, shark_w, size)
#먹을 수 있는 물고기가 없거나 물고기 수가 0일때
if not fish or fishes == 0:
break
#물고기 먹기
f = fish.popleft()
fishes -= 1
cnt+=1
total_time += f[2]
#시작점도 0으로
maps[shark_h][shark_w] = 0
shark_h, shark_w = f[0], f[1]
#먹은 물고기는 이제 0으로 바꿔야함
maps[shark_h][shark_w] = 0
#먹은 물고기 수가 크기와 같다면 size 키움
if cnt == size:
size+=1
cnt = 0
#시작점 초기화
print(total_time)
느낀 점
다른 문제들은 BFS를 통해 최단경로 길이를 사용해서 문제를 진행하는데 이 문제는 BFS응 통해서 갈 수 있는 후보들을 구하여 문제를 진행해야 됐다. 이 문제를 통해서 BFS를 활용해야 하는 새로운 유형을 경험했다.