반응형
Notice
Recent Posts
Recent Comments
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

UP

[백준 14499 : PYTHON] 주사위 굴리기 본문

알고리즘/시뮬레이션

[백준 14499 : PYTHON] 주사위 굴리기

cijbest 2021. 6. 13. 21:32

문제 풀기 : 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

문제

N×M인 지도가 존재한다.

지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 

지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다.

가장 처음에 주사위에는 모든 면에 0이 적혀져 있다.

지도의 각 칸에는 정수가 하나씩 쓰여져 있다.

  • 주사위를 굴렸을 때, 이동한 칸에 쓰여 있는 수가 0이면, 주사위의 바닥면에 쓰여 있는 수가 칸에 복사된다.
  • 0이 아닌 경우에는 칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며, 칸에 쓰여 있는 수는 0이 된다.

 

문제풀이

주사위를 굴릴 때마다 상하좌우로 바뀌는 주사위의 숫자를 어떻게 따져줘야 할 지 몰라서 문제를 못 풀고 있었다. 다른 사람들의 풀이를 봐도 이해를 못하다가 여러 풀이를 보고 깨달았다. 

문제를 최대한 쉽게 설명해보려 한다.

 

우선! 주사위가 움직일 때마다 주사위의 윗면과 밑면을 고정할 수 있는 방법이 무엇인지를 생각해야 한다. 문제에서 전개도를 괜히 준게 아니었다! 전개도는 주사위가 움직일 때마다 변하는 주사위 값의 위치를 지정할 수 있는 유일한 방법이다.

문제에 있는 전개도이다. 핵심은 전개도에 있는 저 숫자들을 고정된 인덱스로 정하는 거다! 예를 들어 1이 있는 위치는 1번 인덱스라고 고정을 하는 것이다. 그렇게 하면 고정된 전개도 내에서 규칙(동서남북)만 찾는다면 값의 위치가 변해도 같은 주사위인 것이다. (코드에서 dice 변수는 각 인덱스의 값들을 저장하는 배열이다.)

아직 이해가 되지 않는다면 다음 규칙을 보자.

1번 인덱스를 기준으로 동쪽으로 이동했을 때의 바뀐 전개도이다. 4개의 인덱스 위치가 변경되었고 다른 방향도 바뀌는 상태를 따져주어 적용한다.

4방향의 변경된 인덱스 위치는 다음과 같다. 바뀐 인덱스대로 값을 변경해주는 함수는 changDiceState이므로 코드에서 확인하면 된다.

 

여기까지 주사위의 상태를 바꿀 수 있다면 다 되었다. 주사위의 윗면은 dice[1]이라는 것과 밑면은 dice[6]이라는 것을 이용하면 나머지 코드는 짤 수 있다.

코드에서는 배열의 인덱스 특성상 0부터 시작하기 때문에 위의 전개도의 인덱스들은 1부터 시작하지만 코드를 작성할 때는 0에 맞추어 작성했다.

 

전체코드

import sys
input = sys.stdin.readline

# 동, 서, 북, 남
direct = [(0, 1), (0, -1), (-1, 0), (1, 0)]

#INPUT
n, m, x, y, k = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(n)]
move = list(map(int, input().split()))

# 주사위에 적힌 수 보관 (전개도)
dice = [0] * 6

def changeDiceState(i):
    if i == 1:
        dice[0], dice[2], dice[3], dice[5] = dice[3], dice[0], dice[5], dice[2]
    elif i == 2:
        dice[0], dice[2], dice[3], dice[5] = dice[2], dice[5], dice[0], dice[3]
    elif i == 3:
        dice[0], dice[1], dice[4], dice[5] = dice[4], dice[0], dice[5], dice[1]
    else:
        dice[0], dice[1], dice[4], dice[5] = dice[1], dice[5], dice[0], dice[4]

for i in move:
    nx = x + direct[i-1][0]
    ny = y + direct[i-1][1]
    
    # 범위 밖에 있으면 명령 건너뛰기
    if nx < 0 or ny < 0 or nx > n - 1 or ny > m - 1:
        continue

    # 주사위 전개도 배치 바꾸기
    changeDiceState(i)

    # 지도 칸의 숫자가 0일 때
    if board[nx][ny] == 0:
        board[nx][ny] = dice[5]
    # 지도 칸의 숫자가 0이 아닐 때
    else:
        dice[5] = board[nx][ny]
        board[nx][ny] = 0
    
    x = nx
    y = ny

    # 주사위 윗면 출력
    print(dice[0])
반응형

'알고리즘 > 시뮬레이션' 카테고리의 다른 글

[백준 14500 : PYTHON] 테트로미노  (9) 2021.06.15
[백준 12100 : PYTHON] 2048 (Easy)  (0) 2021.06.14
[백준 13458 : PYTHON] 시험 감독  (0) 2021.06.13
[백준 3190 : PYTHON] 뱀  (0) 2021.06.13
Comments