<문제 링크>
https://www.acmicpc.net/problem/14499
14499번: 주사위 굴리기
첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지도
www.acmicpc.net
<풀이>
시뮬레이션 문제를 풀 때는 머리로 생각만 하기 보다는 그림을 직접 그려가며 풀면 해답에 쉽게 다가갈 수 있는 것 같다.
우선 문제에서 주사위 전개도를 그림 1과 같이 정의를 했지만, 직접 그려서 풀다 보면 저 형태가 불편하다.
그림 1은 윗면을 기준으로 풀어진 전개도이지만, 나는 바닥면을 기준으로 풀어진 전개도를 가지고 문제를 풀었다.
<예제 2 시뮬레이션>
board에서 파란 원은 board[dx][dy],
오른쪽 전개도에서 파란 원은 바닥면, 붉은 원은 윗면을 뜻함
(*이미지를 먼저 보여준 후에 해당 이미지에 대한 설명을 이미지 아래 글에 덧붙이겠다.)
주사위 dice의 초기값은 모든 면이 0이다.
(1, 1)에서 (1, 2)로 움직였을 때 전개도를 보면 단순히 바닥면에 5를 넣은 것 같지만, 그렇지 않다.
moving의 파라미터인 order에 따라 값들의 자리를 바꾼 후에 dice.bottom에 board[dx][dy] 값을 삽입해야 한다.
2번째 반복문처럼 위아래로 이동하는거에 대한 로직은 쉽게 생각해냈지만, 1과 3과 같이 좌우로 이동하는 경우에 어떤 것들끼리 바꿔야 하는지 생각만 하다가 그림을 그려 보니 한 번에 이해가 됐다.
3 -> 4로 바뀌는 것을 보면 front(0)과 back(5)가 바뀌지 않는 걸 볼 수 있다.
그렇기 때문에 서쪽으로 이동 시 앞뒤는 그대로 유지시키고 좌우와 위아래만 바꾸면 된다는 걸 알 수 있다.
서쪽으로 이동 시 왼쪽면이 바닥면이 되며, 바닥면은 새로운 바닥면의 오른쪽 면이 된다.
주사위 값들은 한 세트(위아래, 좌우, 앞뒤)로 움직이기 때문에 이것들 이용해 자리값들을 교체해주면 된다.
동쪽도 서쪽과 마찬가지로 이동 시 앞뒤는 바뀌지 않는다.
또한, 북 또는 남으로 이동 시 좌우는 변하지 않은 채 주사위 자리를 하나씩 올리거나 내리면 된다.
문제 조건으로 board[dx][dy]가 0이 아닌 경우에는 바닥면에 board값이 복사가 되며 board는 0이 된다.
board 값이 0이라면 dice 바닥면의 값을 복사해주기만 하면 된다.
<코드>
N, M, x, y, K: 세로 크기, 가로 크기, 좌표 x, 좌표 y, 명령 개수
board[][]: (N, M) 크기의 보드판(맵)
dice: 주사위 정보를 담고 있는 주사위 객체
move[]: 동서남북 이동 방향을 저장해둔 리스트
i, j: 첫 시작 좌표 (i, j) (= x, y)
dx, dy: 이동한 좌표값
Dice.moving(): order에 알맞은 방향으로 주사위를 이동 후, 바닥을 기준으로 필드 멤버 변수들 수정해주는 메소드
import sys
class Dice:
def __init__(self):
self.left = 0
self.right = 0
self.top = 0
self.bottom = 0
self.front = 0
self.back = 0
'''
map_value: 이동한 후에 지도 값
operator: 동(1), 서(2), 북(3), 남(4)
'''
def moving(self, order):
if order == 1:
left, right, top, bottom = self.bottom, self.top, self.left, self.right
self.left, self.right, self.top, self.bottom = left, right, top, bottom
elif order == 2:
left, right, top, bottom = self.top, self.bottom, self.right, self.left
self.left, self.right, self.top, self.bottom = left, right, top, bottom
elif order == 3:
front, back, top, bottom = self.top, self.bottom, self.back, self.front
self.front, self.back, self.top, self.bottom = front, back, top, bottom
else:
front, back, top, bottom = self.bottom, self.top, self.front, self.back
self.front, self.back, self.top, self.bottom = front, back, top, bottom
if __name__ == "__main__":
N, M, x, y, K = map(int, sys.stdin.readline().rstrip().split())
board = [[] for _ in range(N)]
dice = Dice()
move = [(0, 1), (0, -1), (-1, 0), (1, 0)]
# create board(map)
for i in range(N):
board[i] = list(map(int, sys.stdin.readline().rstrip().split()))
# position (i, j)
i, j = x, y
# processing order
orders = list(map(int, sys.stdin.readline().rstrip().split()))
for order in orders:
dx, dy = i + move[order - 1][0], j + move[order - 1][1] # 이동한 후에 좌표값
if (0 <= dx < N) and (0 <= dy < M):
i, j = dx, dy # 이동한 좌표값이 범위 내라면 좌표값 저장
if board[dx][dy] == 0: # 현재 보드 값이 0이면 bottom을 board[dx][dy]에 복사
dice.moving(order)
print(dice.top)
board[dx][dy] = dice.bottom
else: # 현재 보드 값이 0이 아니면, bottom에 현재 보드 값 복사 후 보드 값 0으로 만들기
dice.moving(order)
print(dice.top)
dice.bottom = board[dx][dy]
board[dx][dy] = 0
'~2023' 카테고리의 다른 글
[Python] 백준 2636번 문제, 치즈 (0) | 2021.08.20 |
---|---|
[Python] 백준 5430번 문제, AC (0) | 2021.08.02 |
[Python] 백준 6118번 문제, 숨바꼭질 (0) | 2021.08.02 |
[MAC/M1/Issue] M1 칩에서 pod install 이슈 해결하기 (0) | 2021.07.31 |
[Python/미해결] 백준 1068번 문제, 트리 (0) | 2021.07.25 |