출처 : 백준 #16236
시간 제한 | 메모리 제한 |
---|---|
2초 | 512MB |
N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다.
아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다.
아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다. 따라서, 크기가 같은 물고기는 먹을 수 없지만, 그 물고기가 있는 칸은 지나갈 수 있다.
아기 상어가 어디로 이동할지 결정하는 방법은 아래와 같다.
아기 상어의 이동은 1초 걸리고, 물고기를 먹는데 걸리는 시간은 없다고 가정한다. 즉, 아기 상어가 먹을 수 있는 물고기가 있는 칸으로 이동했다면, 이동과 동시에 물고기를 먹는다. 물고기를 먹으면, 그 칸은 빈 칸이 된다.
아기 상어는 자신의 크기와 같은 수의 물고기를 먹을 때 마다 크기가 1 증가한다. 예를 들어, 크기가 2인 아기 상어는 물고기를 2마리 먹으면 크기가 3이 된다.
공간의 상태가 주어졌을 때, 아기 상어가 몇 초 동안 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는지 구하는 프로그램을 작성하시오.
첫째 줄에 공간의 크기 N(2 ≤ N ≤ 20)이 주어진다.
둘째 줄부터 N개의 줄에 공간의 상태가 주어진다. 공간의 상태는 0, 1, 2, 3, 4, 5, 6, 9로 이루어져 있고, 아래와 같은 의미를 가진다.
아기 상어는 공간에 한 마리 있다.
첫째 줄에 아기 상어가 엄마 상어에게 도움을 요청하지 않고 물고기를 잡아먹을 수 있는 시간을 출력한다.
3
0 0 0
0 0 0
0 9 0
0
3
0 0 1
0 0 0
0 9 0
3
4
4 3 2 1
0 0 0 0
0 0 9 0
1 2 3 4
14
6
5 4 3 2 3 4
4 3 2 3 4 5
3 2 9 5 6 6
2 1 2 3 4 5
3 2 1 6 5 4
6 6 6 6 6 6
60
6
6 0 6 0 6 1
0 0 0 0 0 2
2 3 4 5 6 6
0 0 0 0 0 2
0 2 0 0 0 0
3 9 3 0 0 1
48
6
1 1 1 1 1 1
2 2 6 2 2 3
2 2 5 2 2 3
2 2 2 4 6 3
0 0 0 0 0 6
0 0 0 0 0 9
39
feed
1씩 증가level
과 같다면 feed
초기화 후 level
1 증가visited
초기화dist
초기화만약 먹이의 거리가 같을 때의 우선순위는 다음과 같다.
만약 같은 행에 위치하고 있을 때의 우선순위는 다음과 같다.
이러한 생각에 의하면 거리, 행, 열 을 바탕으로 각 숫자들이 작은 순서대로 배치가 되어야 한다.
처음에는 heapq를 쓸 생각을 못하고, 상하좌우로 탐색하는 것에 초점을 두었다.
이에 참고한 블로그는 다음과 같다.
BOJ 16236 · 아기 상어
heapq를 통해 거리, 행, 열 의 순서를 관리한다.
먼저 상하좌우를 탐색하는 것이 아니라, 먹을 수 있는 길인지 확인한다.
확인 과정에서 초기화를 해준다.
확인 과정이 끝나면 상하좌우를 탐색하여 방문할 수 있는 공간을 heapq에 push한다.
visited
가 상하좌우 탐색에 존재해야하는 이유는 visited
가 위쪽에 위치했을 경우 상하좌우 탐색시 중복하여 heapq에 넣게 된다.
# 백준 16236번 아기상어 (그래프 탐색(BFS), 구현)
from sys import stdin
import heapq
input = stdin.readline
n = int(input())
matrix = []
for i in range(n):
matrix.append(list(map(int, input().split())))
def solution(n, matrix):
level = 2 # 아기 상어의 크기
start = (0, 0) # 시작점(9)의 위치
for i in range(n): # 상어 위치 찾기
for j in range(n):
if matrix[i][j] == 9:
start = (i, j)
result = bfs(n, matrix, start, level)
return result
def bfs(n, matrix, start, level):
queue = []
visited = [([False]*n) for _ in range(n)]
dist = 0
feed = 0
answer = 0
heapq.heappush(queue, (dist, start[0], start[1])) # 거리, 행, 열 순
matrix[start[0]][start[1]] = 0
# 상 좌 우 하
dx = [-1, 0, 0, +1]
dy = [0, -1, +1, 0]
while queue:
dist, row, col = heapq.heappop(queue)
# visited[row][col] = True # 여기에 이 코드를 넣으면 시간초과가 뜹니다.
# 이유 : 상 좌 우 하 돌 때 미리 안넣어주면 아래 for문에서 이미 봤던 칸을 또 집어 넣을 수 있게 됨.
if 0 < matrix[row][col] < level: # 먹을 수 있는 길인지 확인
# 초기화
queue = []
matrix[row][col] = 0
visited = [([False]*n) for _ in range(n)]
answer += dist
dist = 0
feed += 1
if feed == level:
level += 1
feed = 0
for i in range(4):
x = row + dx[i]
y = col + dy[i]
if 0<= x < n and 0<= y < n:
if visited[x][y] == False:
if matrix[x][y] <= level:
visited[x][y] = True
heapq.heappush(queue, (dist+1, x, y))
return answer
print(solution(n, matrix))