[Gold I]
https://www.acmicpc.net/problem/13460
13460번: 구슬 탈출 2
첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'
www.acmicpc.net
풀이
조금 복잡했던 BFS 시뮬레이션 문제. 이동 시 빨간 구슬과 파란 구슬이 겹쳤을 때, 각각의 이동 횟수를 계산하여 처리하는 방식이 키포인트.
BFS의 visited 처리는 빨간 구슬과 파란 구슬의 좌표를 이용한다. 몇 번째 이동인 지는 visited로 확인할 필요 없음.
자세한 풀이는 코드의 주석을 참고하여 확인하면 쉽게 이해할 수 있을 것.
AC.
from collections import deque N, M = map(int, input().split()) graph = [list(input()) for _ in range(N)] redr, redc, bluer, bluec = 0, 0, 0, 0 # Red, Blue 구슬 위치 찾기 for r in range(N): for c in range(M): if graph[r][c] == "R": redr, redc = r, c if graph[r][c] == "B": bluer, bluec = r, c visited = [] deq = deque([(redr, redc, bluer, bluec, 0)]) dr = [1, 0, -1, 0] dc = [0, 1, 0, -1] success = [] def move(nr, nc, dr, dc): moveCnt = 0 # 벽 또는 구멍을 만날 때까지 이동 while graph[nr+dr][nc+dc] != "#" and graph[nr][nc] != "O": nr, nc = nr+dr, nc+dc moveCnt += 1 return nr, nc, moveCnt while deq: redr, redc, bluer, bluec, time = deq.popleft() time += 1 if time > 10: continue for i in range(4): redlr, redlc, redMove = move(redr, redc, dr[i], dc[i]) bluelr, bluelc, blueMove = move(bluer, bluec, dr[i], dc[i]) # 파란 구슬이 구멍에 들어갔다면 실패 if graph[bluelr][bluelc] == "O": continue # 파란 구슬이 구멍에 들어가지 않고, 빨간 구슬이 구멍에 들어갔다면 성공 if graph[redlr][redlc] == "O": success.append(time) # 이동 후 겹쳐있다면, 더 많이 이동한 구슬을 한 칸 당김 if redlr == bluelr and redlc == bluelc: if redMove > blueMove: redlr, redlc = redlr-dr[i], redlc-dc[i] else: bluelr, bluelc = bluelr-dr[i], bluelc-dc[i] # visited 확인 및 방문 체크 if (redlr, redlc, bluelr, bluelc) in visited: continue visited.append((redlr, redlc, bluelr, bluelc)) deq.append((redlr, redlc, bluelr, bluelc, time)) if success: print(min(success)) else: print(-1)