Y행 X열 격자에 백조가 두 마리 살고 있다. 호수 얼음으로 덮여 있으며, 매일 물과 맞닿아 있는 얼음이 한 겹씩 녹아 물이 된다. 백조는 물에서만 상하좌우로 이동할 수 있을 때, 두 백조가 만날 수 있는 최소 날짜를 구하는 문제이다.
이 문제는 얼음이 하루에 한 겹씩 녹음 , 백조가 현재 이동할 수 있는 범위 체크 두 가지 처리를 해줘야 한다.
즉, 빙판BFS, 백조BFS처럼 BFS를 2개 돌리면서 날이 지날 때마다 (백조 이동 처리) -> (빙판 녹이기 처리) -> (날짜 전환) 순서로 진행해주면 된다.

아이디어가 어렵다...
내 코드가 1200ms 정도 나오고, 파이썬 중 런타임이 빠른 사람의 코드는 600ms정도로 2배 빠르게 나왔다.
또, 태그에 분리 집합이 있었는데, 내 풀이는 분리 집합을 전혀 사용하지 않아서 빠른 코드들이 분리 집합을 사용한 건 아닐까? 라고 생각을 했다.
코드를 분석해보니 분리 집합을 사용한 풀이가 맞았고, 이 방법도 알아두면 좋을 것 같아 큰 흐름만 간단하게 정리했다.
# 백준 3197
import io
from collections import deque
input = io.BufferedReader(io.FileIO(0), 1<<18).readline
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
def solve(Y, X, grid):
# 백조의 초기 위치 저장
swan = []
for y in range(Y):
for x in range(X):
if grid[y][x] == 'L':
swan.append((y, x))
visited = [[0] * X for _ in range(Y)]
swanQ = deque()
swanNextQ = deque()
waterQ = deque()
waterNextQ = deque()
# 백조와 물의 초기 위치 큐에 추가
swanQ.append(swan[0])
visited[swan[0][0]][swan[0][1]] = 1
for y in range(Y):
for x in range(X):
if grid[y][x] != 'X':
waterQ.append((y, x))
day = 0
while True:
# 백조 이동 BFS
while swanQ:
curY, curX = swanQ.popleft()
for i in range(4):
nextX = curX + dx[i]
nextY = curY + dy[i]
if 0 <= nextX < X and 0 <= nextY < Y and visited[nextY][nextX] == 0:
visited[nextY][nextX] = 1
# 백조를 만난 경우
if nextX == swan[1][1] and nextY == swan[1][0]:
return day
# 다음날 이동 가능한 칸인 경우
if grid[nextY][nextX] == 'X':
swanNextQ.append((nextY, nextX))
# 지금 이동 가능한 칸인 경우
else:
swanQ.append((nextY, nextX))
# 얼음 녹이기 BFS
while waterQ:
curY, curX = waterQ.popleft()
for i in range(4):
nextX = curX + dx[i]
nextY = curY + dy[i]
if 0 <= nextX < X and 0 <= nextY < Y and grid[nextY][nextX] == 'X':
grid[nextY][nextX] = '.'
waterNextQ.append((nextY, nextX))
# 다음날 처리
swanQ = swanNextQ
swanNextQ = deque()
waterQ = waterNextQ
waterNextQ = deque()
day += 1
def main():
Y, X = map(int, input().split())
grid = []
for _ in range(Y):
grid.append(list(input().decode().strip()))
print(solve(Y, X, grid))
main()