티스토리 뷰

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번 자리에는 4가, 3번 자리에는 1, 4번 자리에는 6, 6번 자리에는 3이 온다.

 

rolled = {
    1: [o[3], o[1], o[0], o[5], o[4], o[2]],  # 동쪽
    2: [o[2], o[1], o[5], o[0], o[4], o[3]],  # 서쪽
    3: [o[4], o[0], o[2], o[3], o[5], o[1]],  # 북쪽
    4: [o[1], o[5], o[2], o[3], o[0], o[4]]   # 남쪽
}

 

따라서 이런 식으로 동서남북으로 굴릴 경우, 각 주사위의 어떤 면이 어느 위치로 이동하는지를 미리 배열로 저장해두자.

 

축가로 처음에 1, 2, 3, 4, 5, 6으로 할지, 아니면 2, 1, 4, 3, 5, 6으로 할지 등 어느 기준으로 주사위를 표현하는지에 따라 다르긴 하지만, 맨 윗면과 바닥면의 위치가 고정된다. 내 경우엔 배열에서 첫 번째 원소는 윗면의 숫자가, 마지막 원소는 바닥면의 숫자가 저장된다. 이는 게임을 진행하면서 매우 유용하게 활용된다. 윗면을 출력하기도 하고, 바닥면에 새 값을 저장하거나 바닥면 값을 지도 칸에 옮기기도 해서 바닥면과 윗면 값이 동시에 필요하기 때문이다.

 

 

 

2. 정답 코드

import sys

input = sys.stdin.readline


def roll_the_dice(o, d):
    rolled = {
        1: [o[3], o[1], o[0], o[5], o[4], o[2]],
        2: [o[2], o[1], o[5], o[0], o[4], o[3]],
        3: [o[4], o[0], o[2], o[3], o[5], o[1]],
        4: [o[1], o[5], o[2], o[3], o[0], o[4]]
    }
    return rolled[d]


def validate_coordinate(u, z):
    return True if 0 <= u < N and 0 <= z < M else False
    

def is_movable(u, z, d):
    du, dz = u + directions[d][0], z + directions[d][1]
    return (True, du, dz) if validate_coordinate(du, dz) else (False, u, z)


# main
N, M, x, y, k = map(int, input().split())
maps = [list(map(int, input().split())) for _ in range(N)]
commands = list(map(int, input().split()))

directions = ['', (0, 1), (0, -1), (-1, 0), (1, 0)]
dice = [0] * 6  # 주사위 각 면에 적힌 숫자
top = 1

for cmd in commands:
    result, x, y = is_movable(x, y, cmd)
    if not result:
        continue

    dice = roll_the_dice(dice, cmd)
    top = dice[0]
    bottom = dice[-1]
    if maps[x][y] == 0:
        maps[x][y] = bottom
    else:
        dice[-1] = maps[x][y]
        maps[x][y] = 0
    print(top)
728x90