4179번: 불!
입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다. 다음 입력으로 R줄동안 각각의 미로 행이 주어진다. 각각의 문자
www.acmicpc.net
알고리즘 : BFS
난이도 : 골드Ⅳ
1. 문제요약
- 2차원 맵이 주어진다. '#'은 벽을, '.'은 빈 공간을 나타낸다. 또한 'J'는 사람을, 'F'는 불을 나타낸다.
- 매 시간 불은 사방으로 퍼지고, 사람 또한 사방으로 이동할 수 있다.
- 이때 사람이 불을 피해 맵에서 탈출할 수 있는 최단시간을 출력해야 한다. 탈출이 불가능할 경우 IMPOSSIBLE을 출력한다.
2. 구현과정
- BFS 문제로 앞서 풀었던 불 문제와 거의 동일한 문제이다.
- 일단 불과 사람의 이동로직을 간단히 하고 탈출조건을 명확히 파악하기 위해 '!'로 맵을 패딩해 주었다.
- 맵을 따라 이동하는 것이 두 가지라는 점이 특이사항인데, 매 시간마다 불을 먼저 확산시킨 뒤에 사람을 이동시켜가며 탈출하는 과정을 구현해나간다.
3. 파이썬 코드
from collections import deque
import sys
input = lambda: sys.stdin.readline().rstrip()
r, c = map(int, input().split())
# 맵초기화 : '!'으로 패딩
field = [['!'] * (c + 2)]
for _ in range(r):
field.append(['!'] + list(input()) + ['!'])
field.append(['!'] * (c + 2))
# 불, 사람 각각 큐 구현 / 처음좌표 찾기
fire, human = deque(), deque()
for i in range(r + 2):
for j in range(c + 2):
if field[i][j] == 'F':
fire.append([i, j])
if field[i][j] == 'J':
human.append([i, j, 0])
# 이동방향
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
# bfs 수행 : 불을 상하좌우로 확산시킨 후 사람의 이동방향 탐색
answer = False
while human:
# 불 확산
tmp = deque()
while fire:
xfire, yfire = fire.popleft()
for i in range(4):
nxfire, nyfire = xfire + dx[i], yfire + dy[i]
if field[nxfire][nyfire] in '.J': # 불이 확산가능한 곳
tmp.append([nxfire, nyfire])
field[nxfire][nyfire] = 'F' # 불 확산된 곳 갱신
fire = tmp
# 사람 이동방향 탐색
tmp2 = deque()
while human:
xman, yman, tman = human.popleft()
for i in range(4):
nxman, nyman, ntman = xman + dx[i], yman + dy[i], tman + 1
if field[nxman][nyman] == '!': # 탈출성공
answer = ntman
if field[nxman][nyman] == '.':
tmp2.append([nxman, nyman, ntman])
field[nxman][nyman] = 'J' # 사람이 이동한 곳 갱신
human = tmp2
# while문 탈출조건
if answer:
print(answer)
break
else:
print('IMPOSSIBLE')
'공부 > 알고리즘 문제풀이 기록' 카테고리의 다른 글
[백준 2468] 안전 영역 (0) | 2023.12.27 |
---|---|
[백준 5014] 스타트링크 (1) | 2023.12.18 |
[백준 2667] 단지번호붙이기 (0) | 2023.12.15 |
[백준 2583] 영역 구하기 (0) | 2023.12.14 |
[백준 5427] 불 (0) | 2023.12.13 |