문제링크
https://www.acmicpc.net/problem/16918
문제설명
문제
봄버맨은 크기가 R×C인 직사각형 격자판 위에서 살고 있다. 격자의 각 칸은 비어있거나 폭탄이 들어있다.
폭탄이 있는 칸은 3초가 지난 후에 폭발하고, 폭탄이 폭발한 이후에는 폭탄이 있던 칸이 파괴되어 빈 칸이 되며, 인접한 네 칸도 함께 파괴된다. 즉, 폭탄이 있던 칸이 (i, j)인 경우에 (i+1, j), (i-1, j), (i, j+1), (i, j-1)도 함께 파괴된다. 만약, 폭탄이 폭발했을 때, 인접한 칸에 폭탄이 있는 경우에는 인접한 폭탄은 폭발 없이 파괴된다. 따라서, 연쇄 반응은 없다.
봄버맨은 폭탄에 면역력을 가지고 있어서, 격자판의 모든 칸을 자유롭게 이동할 수 있다. 봄버맨은 다음과 같이 행동한다.
- 가장 처음에 봄버맨은 일부 칸에 폭탄을 설치해 놓는다. 모든 폭탄이 설치된 시간은 같다.
- 다음 1초 동안 봄버맨은 아무것도 하지 않는다.
- 다음 1초 동안 폭탄이 설치되어 있지 않은 모든 칸에 폭탄을 설치한다. 즉, 모든 칸은 폭탄을 가지고 있게 된다. 폭탄은 모두 동시에 설치했다고 가정한다.
- 1초가 지난 후에 3초 전에 설치된 폭탄이 모두 폭발한다.
- 3과 4를 반복한다.
폭탄을 설치해놓은 초기 상태가 주어졌을 때, N초가 흐른 후의 격자판 상태를 구하려고 한다.
예를 들어, 초기 상태가 아래와 같은 경우를 보자.
...
.O.
...
1초가 지난 후에는 아무 일도 벌어지지 않기 때문에, 위와 같다고 볼 수 있다. 1초가 더 흐른 후에 격자판의 상태는 아래와 같아진다.
OOO
OOO
OOO
1초가 지난 후엔 가운데에 있는 폭탄이 폭발해 가운데 칸과 인접한 네 칸이 빈 칸이 된다.
O.O
...
O.O
입력
첫째 줄에 R, C, N (1 ≤ R, C, N ≤ 200)이 주어진다. 둘째 줄부터 R개의 줄에 격자판의 초기 상태가 주어진다. 빈 칸은 '.'로, 폭탄은 'O'로 주어진다.
출력
총 R개의 줄에 N초가 지난 후의 격자판 상태를 출력한다.
문제풀이
생각보다 어렵게 생각하고 헷갈려 시간이 오래걸린 문제였다.
폭탄이 있는 좌표를 큐에 삽입하고,
폭탄이 폭발하는 로직에서 하나씩 pop시켜 해당 위치와 상하좌우 위치좌표까지 상태를 변경하는건 기존에 풀었던 BFS와 매우 흡사하다고 생각했다.
반복문을 통해서 해당 (3),(4) 문을 순차적으로 하나씩 실행한다.
(1) (초기) 봄버맨이 폭탄 'O' 셋팅
(2) 아무것도 안함
(3) 폭탄 설치 안된 나머지 칸에 폭탄 전부 설치
(4) 3초 전에 설치된 폭탄 폭발.
그냥 순차적으로 격자판 상태를 변경하며 진행해도 예제로 주어진 테스트케이스는 통과한다.
하지만 제출을 하면 실패한다.
핵심은
- 3초 전에 설치된 폭탄 폭발.
- 3과 4를 반복
시간이 흐르고 시간내에 반복하는 로직이 있기 때문에
이미지의 2번과 4번에 해당한 격자판 상태,
즉, 3번 로직들을 실행하기 전의 격자판 상태를 기억하는 로직을 만들자!
3번 과정 전에 기억한 폭탄들의 좌표를 큐에 삽입하는 것이 핵심이었다.
이제 이 큐를 4번과정인 폭발로직에 넘겨 활용하면 된다.
코드
import sys
from collections import deque
input = sys.stdin.readline
R, C, N = map(int, input().split())
graph = [[0 for _ in range(C)] for _ in range(R)]
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
queue = deque()
# 입력값 받기 (격자판 초기상태)
for i in range(R):
graph[i] = list(input().rstrip())
# (1) 봄버맨이 일부칸에 폭탄 설치. (이미 입력값으로 받음)
# 폭탄('O')이 있는 좌표들 큐에 삽입하기
def memoBomb():
for i in range(R):
for j in range(C):
if graph[i][j] == 'O':
queue.append((i, j))
return queue
# (2) 폭탄 모든칸에 설치
def plantBombs():
global R, C
for i in range(R):
for j in range(C):
graph[i][j] = 'O'
# (3) 3초 전에 설치된 폭탄이 모두 폭발하는 로직
def explode(bombQueue):
global R, C
while bombQueue:
curX, curY = queue.popleft()
graph[curX][curY] = '.' # 폭탄 폭발한 상태.
for i in range(4):
nx = curX + dx[i]
ny = curY + dy[i]
if 0 <= nx < R and 0 <= ny < C and graph[nx][ny] == 'O':
graph[nx][ny] = '.'
# N초 동안 1초마다 해당 로직 실행.
def solution():
global N
# (1) 1초동안 아무것도 안하는 상태
N -= 1
while N:
# 폭탄 채우기 바로 전 상황 기억 (폭탄 좌표 큐에 삽입).
bombQueue = memoBomb()
# (2) 폭탄 없는 칸에 전부 폭탄 채우기
plantBombs()
N -= 1
# 시간 다 흘렀으면 반복문 종료
if N <= 0:
break
# (3) 폭탄 터뜨리기
explode(bombQueue)
N -= 1
# N초 흐른 후에 격자판 상태 출력
for row in graph:
print("".join(row))
if __name__ == "__main__":
solution()
'알고리즘 > 백준' 카테고리의 다른 글
[백준 1697] 숨바꼭질 (with Python / BFS) (0) | 2023.08.23 |
---|---|
[백준 13023] ABCDE (with Python / DFS, 백트래킹) (0) | 2023.08.22 |
[백준 7576] 토마토 (with Python / BFS) (0) | 2023.08.13 |
[백준 2178] 미로 탐색 (with Python / BFS) (0) | 2023.08.12 |
[백준 1256] 사전 (with Python / DP) (0) | 2023.08.11 |