N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다.
아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다.
아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다. 따라서, 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다.
아기 상어가 어디로 이동할지 결정하는 방법은 아래와 같다.
-0 더 이상 먹을 수 있는 물고기가 공간에 없다면 아기 상어는 엄마 상어에게 도움을 요청한다.
아기 상어의 이동은 1초 걸리고, 물고기를 먹는데 걸리는 시간은 없다고 가정한다. 즉, 아기 상어가 먹을 수 있는 물고기가 있는 칸으로 이동했다면, 이동과 동시에 물고기를 먹는다. 물고기를 먹으면, 그 칸은 빈 칸이 된다.
아기 상어는 자신의 크기와 같은 수의 물고기를 먹을 때 마다 크기가 1 증가한다. 예를 들어, 크기가 2인 아기 상어는 물고기를 2마리 먹으면 크기가 3이 된다.
공간의 상태가 주어졌을 때, 아기 상어가 몇 초 동안 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는지 구하는 프로그램을 작성하시오.
첫째 줄에 공간의 크기 N(2 ≤ N ≤ 20)이 주어진다.
둘째 줄부터 N개의 줄에 공간의 상태가 주어진다. 공간의 상태는 0, 1, 2, 3, 4, 5, 6, 9로 이루어져 있고, 아래와 같은 의미를 가진다.
아기 상어는 공간에 한 마리 있다.
첫째 줄에 아기 상어가 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는 시간을 출력한다.
import sys
input = sys.stdin.readline
from collections import deque
N = int(input())
maps = [list(map(int, input().split())) for _ in range(N)]
# 상어 초기 위치
for h in range(N):
for w in range(N):
if maps[h][w] == 9:
by = h; bx = w
break
# 초기 상어 크기
shark = 2
def BFS(a, b):
distance = [[0] * N for _ in range(N)] # 시간 당 최대 이동
visited = [[False] * N for _ in range(N)] # 방문 여부
q = deque()
q.append((a, b))
dy = [0, 1, 0, -1]
dx = [-1, 0, 1, 0]
lst = []
while q:
y, x = q.popleft()
for i in range(4):
ny = y + dy[i]
nx = x + dx[i]
if ny < 0 or ny >= N or nx < 0 or nx >= N:
continue
if 0 <= ny < N and 0 <= nx < N and not visited[ny][nx]:
# 방문하지 않은 곳이면서 자신의 크기보다 큰 물고기가 아니라면
if maps[ny][nx] <= shark:
q.append((ny, nx))
visited[ny][nx] = True
distance[ny][nx] = distance[y][x] + 1
# 0 : 빈 칸 제외 + 아기 상어 크기보다 작아야 가능
if maps[ny][nx] < shark and maps[ny][nx] != 0:
lst.append([ny, nx, distance[ny][nx]])
# 거리가 가까운 물고기부터
# 그 다음은 가장 위에 있는 물고기부터
# 또 그 다음은 가장 왼쪽에 있는 물고기부터
return sorted(lst, key=lambda x : (-x[2], -x[0], -x[1]))
time = 0 # 시간
cnt = 0 # 먹은 물고기 수
while True:
s = BFS(by, bx)
# 엄마 상어에게 도움을 요청
if len(s) == 0:
break
cy, cx, distance = s.pop()
time += distance
maps[cy][cx] = maps[by][bx] = 0
cnt += 1
if cnt == shark:
shark += 1
cnt = 0
maps[cy][cx] = 0
by, bx = cy, cx
print(time)
알고리즘 유형 : BFS/DFS
BFS의 반환 값 설명
이렇게 한 이유는 deque
의 popleft()
를 사용할 수 없었기 때문에 위와 같이 람다식으로 정렬을 하게 된 후 pop()
을 하게 되면 그 반대부터 나오기 때문이다.
이것이 코딩테스트다 with 파이썬 - 아기 상어
모범 답안 - 아기 상어