[BFS] 백준 17086. 아기 상어 2
오늘 다룰 문제는 BFS(너비 우선 탐색)의 정석 같은 문제입니다.
특히 다수의 시작점에서 동시에 BFS를 수행하는 방식이 핵심이며, 최단 거리 문제에서 매우 자주 등장합니다.
한 칸마다 가장 가까운 아기 상어와의 거리를 구하는 문제이기 때문에, 모든 상어에서 동시에 퍼져나가며 각 칸의 최단 거리를 갱신해주는 전략이 유효합니다.
1. 문제: 백준 17086. 아기 상어 2
- 단계: 🥈 실버 2단계
- 주제:
- 출처: https://www.acmicpc.net/problem/17086
문제
N×M 크기의 공간에 아기 상어 여러 마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 아기 상어가 최대 1마리 존재한다.
어떤 칸의 안전 거리는 그 칸과 가장 거리가 가까운 아기 상어와의 거리이다. 두 칸의 거리는 하나의 칸에서 다른 칸으로 가기 위해서 지나야 하는 칸의 수이고, 이동은 인접한 8방향(대각선 포함)이 가능하다.
안전 거리가 가장 큰 칸을 구해보자.
입력
첫째 줄에 공간의 크기 N과 M(2 ≤ N, M ≤ 50)이 주어진다. 둘째 줄부터 N개의 줄에 공간의 상태가 주어지며, 0은 빈 칸, 1은 아기 상어가 있는 칸이다. 빈 칸과 상어의 수가 각각 한 개 이상인 입력만 주어진다.
출력
첫째 줄에 안전 거리의 최댓값을 출력한다.
예제 입력 1
5 4
0 0 1 0
0 0 0 0
1 0 0 0
0 0 0 0
0 0 0 1
예제 출력 1
2
예제 입력 2
7 4
0 0 0 1
0 1 0 0
0 0 0 0
0 0 0 1
0 0 0 0
0 1 0 0
0 0 0 1
예제 출력 2
2
2. 문제 풀이
이 문제는 다음과 같이 풀 수 있습니다.
✔️ 접근 방법 요약
- 아기 상어가 있는 모든 위치를 큐에 넣고 멀티 소스 BFS를 수행합니다.
- BFS를 통해 빈 칸으로 이동하며, 각 칸에 가장 가까운 상어와의 거리를 계산합니다.
- 최종적으로 계산된 거리 중에서 가장 큰 값을 출력하면 됩니다.
✔️ 핵심 아이디어: "멀티 소스 BFS"
보통 BFS는 한 지점에서 출발합니다. 그러나 이번 문제는 모든 상어의 위치에서 동시에 퍼져 나가는 것이 효율적입니다.
예를 들어 상어가 3마리 있다면, 이 3개의 좌표를 큐에 모두 넣고, 동시에 탐색을 시작하여 가장 가까운 상어로부터의 거리를 계산할 수 있습니다.
구현 코드
from collections import deque
def bfs(N, M, grid):
directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (1, 1), (1, -1), (-1, 1), (-1, -1)]
queue = deque()
visited = [[False] * M for _ in range(N)]
max_dist = 0
for i in range(N):
for j in range(M):
if grid[i][j] == 1:
queue.append((i, j, 0))
visited[i][j] = True
while queue:
cur_x, cur_y, cur_d = queue.popleft()
for dx, dy in directions:
next_x, next_y = cur_x + dx, cur_y + dy
if 0 <= next_x < N and 0 <= next_y < M:
if not visited[next_x][next_y]:
visited[next_x][next_y] = True
max_dist = max(max_dist, cur_d + 1)
queue.append((next_x, next_y, cur_d + 1))
return max_dist
def main():
N, M = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(N)]
print(bfs(N, M, grid))
if __name__ == '__main__':
main()
시간 복잡도
- BFS는 각 칸을 최대 1번만 방문하므로,
- 전체 시간 복잡도는 O(N × M)입니다.
- N, M ≤ 50이므로 최대 2,500칸, 시간 제한 내에 충분히 통과 가능합니다.
3. 마무리
이 문제는 다음과 같은 점에서 BFS 연습에 매우 좋습니다:
- 멀티 소스 BFS를 어떻게 쓰는지 체득할 수 있고,
- 8방향 이동을 직접 구현해볼 수 있으며,
- 거리 개념과 BFS의 조합이 자연스럽게 드러나는 문제입니다.
그래서 실버 2지만 충분히 쉬운 문제로 느껴질 수 있고, BFS 입문 또는 복습용 문제로 강력 추천드립니다.
읽어주셔서 감사합니다.