인내의 도미노 장인 호석
문제
사람을 화나게 하는 법은 다양하다. 그 중에서도 악질은 바로 열심히 세워놓은 도미노를 넘어뜨리는 것이다. 이번에 출시된 보드 게임인 "너 죽고 나 살자 게임"은 바로 이 점을 이용해서 2명이 공격과 수비를 하는 게임이다. 공격수는 도미노를 계속 넘어뜨리고 수비수는 도미노를 계속 세우려고 한다. 본 게임은 다음과 같이 진행된다.
- N 행 M 열의 2차원 격자 모양의 게임판의 각 격자에 도미노를 세운다. 각 도미노는 1 이상 5 이하의 높이를 가진다.
- 매 라운드는 공격수가 먼저 공격하고, 수비수는 공격이 끝난 뒤에 수비를 한다.
- 공격수는 특정 격자에 놓인 도미노를 동, 서, 남, 북 중 원하는 방향으로 넘어뜨린다. 길이가 K인 도미노가 특정 방향으로 넘어진다면, 그 방향으로 K-1 개의 도미노들 중에 아직 넘어지지 않은 것들이 같은 방향으로 연달아 넘어진다. 이 때, 당연히 도미노의 특성상, 연쇄적으로 도미노가 넘어질 수 있다. 이미 넘어진 도미노가 있는 칸을 공격한 경우에는 아무 일이 일어나지 않는다.
- 수비수는 넘어져 있는 도미노들 중에 원하는 것 하나를 다시 세울 수 있다. 넘어지지 않은 도미노를 세우려고 하면 아무 일이 일어나지 않는다.
- 총 R 번의 라운드동안 3, 4번 과정이 반복된다. 매 라운드마다 공격수가 해당 라운드에 넘어뜨린 도미노의 개수를 세고, R 라운드에 걸친 총합이 곧 공격수의 점수가 된다.

도미노 공격에 대한 예시 그림이다. 그림의 빨간 숫자들은 넘어진 도미노들을 의미한다.
예를 들어 {3, 1, 2, 2, 2} 높이의 도미노가 일렬로 서 있는 과정에서 3번을 오른쪽으로 밀면 왼쪽의 3개가 오른쪽으로 넘어지게 된다. 이에 따라 새롭게 넘어진 도미노들의 연쇄작용이 발생하는데, 이 과정에서 4번째에 위치한 길이 2짜리 도미노도 넘어지게 된다. 이어서 마지막 도미노까지 쓰러지게 되는 것이다.
인내를 빼면 시체라고 자부하는 호석이는 당신의 공격을 이겨내고자 수비수를 자처했다. 초기 도미노 판의 상태와, 각 라운드에서 둘의 행동의 기록을 받아서 공격수의 점수와 게임판의 최종 상태를 출력하는 프로그램을 작성하라.
입력
첫 번째 줄에는 게임판의 행 개수 N, 열 개수 M, 라운드 횟수 R 이 주어진다.
이어서 N개의 줄에 게임판의 상태가 주어진다. 1행부터 주어지며, M 개의 숫자는 각 격자에 놓인 도미노의 길이를 의미한다.
이어서 R×2 개의 줄에 걸쳐서 공격수와 수비수의 행동이 주어진다. 각 라운드는 두 줄로 이뤄지며, 첫 줄은 공격수, 두번째 줄은 수비수의 행동이 주어진다. 공격수의 행동은 "X Y D"로 주어진다. 이는 X행 Y열의 도미노를 D 방향으로 민다는 뜻이다. D는 E, W, S, N 중 하나이며 각각 동, 서, 남, 북 방향을 의미한다. 수비수의 행동은 "X Y"로 주어진다. 이는 X행 Y열의 도미노를 다시 세운다는 뜻이다.
만약 이미 넘어진 격자의 도미노를 공격수가 넘어뜨리려 할 때에는 아무 일도 일어나지 않는다. 또한 만약 넘어지지 않은 도미노를 수비수가 세우려고 할 때에도 아무 일도 일어나지 않는다.
출력
첫 줄에 공격수의 점수를 출력한다.
이어서 게임판의 상태를 N 줄에 걸쳐서 출력한다. 각 격자마다 넘어진 것은 F, 넘어지지 않은 것은 S 를 공백으로 구분하여 출력한다.
제한
입력되는 모든 값은 양의 정수이다.
- 1 ≤ N, M ≤ 100
- 1 ≤ R ≤ 10,000
- 1 ≤ 도미노의 길이 ≤ 5
- 공격수와 수비수는 격자를 벗어나는 행동은 하지 않는다.
구현 문제라 하나씩 생각하면서 풀었다.
한 라운드에 공격자, 수비자 순서로 하였고
공격자의 경우 처음 위치의 도미노 높이를 저장.
해당 도미노가 일어나있다면 현재 넘어뜨릴 수 있는 높이 - 1과 현재 도미노의 높이 - 1 중에 큰 값을 저장.
그리고 공격자의 포인트 증가.
만약 넘어져있다면 현재 넘어뜨릴 수 있는 높이만 1 줄어듦.
해당 과정을 거친 후 해당 도미노를 넘어뜨림.
그리고 다음 도미노로 이동하고 범위 내인지 확인.
만약 이 높이가 0이하이면 공격자 끝.
그리고 수비자는 넘어진걸 세움.
이 과정을 R번 반복
import sys
input = sys.stdin.readline
N, M, R = map(int,input().split())
domino_h = [list(map(int,input().split())) for _ in range(N)]
domino = [['S'] * M for _ in range(N)]
# E W N S
dirs = {'E':(0,1),'W':(0,-1),'N':(-1,0),'S':(1,0)}
cnt = 0
for _ in range(R):
## 공격
X, Y, D = input().split()
X, Y = int(X) - 1, int(Y) - 1
# 방향 저장
dir = dirs[D]
# 높이 저장
H = domino_h[X][Y]
# 만약 F 이면 아무 변화가 없음
if domino[X][Y] == 'F':
pass
else:
# 높이가 0 이상이여야 다른 도미노를 넘어뜨릴 수 있음.
while H > 0:
# 해당 위치의 도미노가 일어나있으면
# 현재 높이 - 1과 해당 도미노의 높이 - 1 중 큰 값을 저장
# 공격자의 포인트를 증가
if domino[X][Y] == 'S':
H = max(H - 1, domino_h[X][Y] - 1)
cnt += 1
# 도미노가 넘어져있다면
# 높이만 줄어듦
else:
H -= 1
# 해당 도미노를 넘어지게함.
domino[X][Y] = 'F'
# 다음 도미노
X, Y = X + dir[0], Y + dir[1]
# 다음 도미노가 범위 내 인가?
if 0 <= X < N and 0 <= Y < M:
pass
else:
break
## 수비
X, Y = map(int,input().split())
X, Y = X - 1, Y - 1
domino[X][Y] = 'S'
print(cnt)
for do in domino:
print(*do)
'@@@ 알고리즘 > 백준 스터디' 카테고리의 다른 글
백준20928(걷는 건 귀찮아) - 해결 (0) | 2022.03.03 |
---|---|
백준16441 (아기돼지와 늑대) - 해결 (0) | 2022.02.24 |
백준 4658(삼각형 게임) - 해결 (0) | 2022.02.21 |
백준 1719(택배) - 참고 해결 (0) | 2022.02.19 |
백준 14550(마리오 파티) - 해결 (0) | 2022.02.17 |