ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] 백준 14499번 문제 풀이 - 주사위굴리기
    코딩테스트 2025. 8. 21. 19:13

    문제 링크

    https://www.acmicpc.net/problem/14499

    문제 이해

    이 문제는 주사위를 동,서,북,남 방향으로 굴렸을 때 윗면의 눈금을 출력하는 문제입니다.

    주사위는 처음 시작할 때 모든 면이 0입니다.

    굴릴때 격자가 0이라면 주사위 밑면의 눈금이 격자로 복사되고

    굴릴때 격자가 0이 아니면 격자의 눈금이 주사위로 복사되고 격자의 눈금은 0이 됩니다.

    그리고 지도의 바깥으로 나가면 아무런 동작을 하지 않습니다.

    아이디어

    처음에 제가 생각했던 아이디어는 다음과 같습니다.

    주사위의 윗면이 1일때 동서남북으로 굴릴때 밑면의 주사위 눈금이 뭐가 나오는지 확인하는 것입니다.

    상상으로는 안됐기 때문에 종이로 전개도를 그리고 접어서 확인해봤습니다…

    그래서 나온 결과는 다음과 같았습니다.

    # dice_direction = {
    #     1 : [3,4,2,5],
    #     2 : [3,4,6,1],
    #     3 : [6,1,2,5],
    #     4 : [5,2,1,6],
    #     5 : [3,4,1,6],
    #     6 : [3,4,5,2]
    # }
    

    이제 동서남북 방향은 다구했고 반대면 = 7-현재면 으로 구할 수 있었기 때문에 바닥면의 눈금을 최신화 시키고 7-바닥면 해서 출력하면 될거라고 생각했습니다.

    근데 여기서 문제가 좌우로 굴렸을 경우 제가 구했던 방향대로 주사위 눈금이 안나오는 것이 문제였습니다.

     

    그래서 답이 다르게 나왔고, 결국 답을 찾아봤습니다 ㅎㅎ

    찾아본 결과 동,서,북,남으로 굴릴 때 주사위의 눈금 위치가 어떻게 바뀌는지에 대한 규칙이 있었습니다.

    위, 뒤, 오른쪽, 왼쪽, 앞쪽, 바닥1,2,3,4,5,6으로 하고 동쪽으로 움직이면 [1,2,3,4,5,6]이 [3,2,6,1,5,4]로 바뀌는 것처럼 규칙이 있었습니다.

    이 규칙을 적용하여 굴릴때마다 주사위 눈금의 위치가 변하는 것을 구할수 있었고 저 배열의 0번째 인덱스를 출력하고, 5번째 인덱스를 최신화 하면 위를 출력하고 바닥을 최신화 할 수 있었습니다.

    시간복잡도

    이 코드의 K번만큼 반복하기 때문에 O(K) K = 1000이므로 가능합니다.

    코드 구현

    이 아이디어를 코드로 구현하면 다음과 같습니다.

    n, m, x, y, k = map(int, input().split())
    
    board = []
    # 동 서 북 남
    dx = [0, 0, -1, 1]
    dy = [1, -1, 0, 0]
    
    dice = [0, 0, 0, 0, 0, 0]
    
    def turn(dir):
        global dice
        a, b, c, d, e, f = dice
        if dir == 1: #동
            dice = [d, b, a, f, e, c]
    
        elif dir == 2: #서
            dice = [c, b, f, a, e, d]
    
        elif dir == 3: #북
            dice = [e, a, c, d, f, b]
    
        else:
            dice = [b, f, c, d, a, e]
    
    for i in range(n):
        board.append(list(map(int, input().split())))
    
    moves = list(map(int, input().split()))
    
    nx, ny = x, y
    for move in moves:
        nx += dx[move-1]
        ny += dy[move-1]
    		
    		# 밖으로 나갈 때
        if not ((0<=ny<n) and (0<=nx<m)):
    		    # 움직이기 전 상태로 돌리고
            nx -= dx[move-1] 
            ny -= dy[move-1]
            continue # 아무 동작도 하지 않음
        turn(move) # 주사위 굴리기
        # 격자가 0 일때
        if board[nx][ny] == 0:
            board[nx][ny] = dice[-1]
        # 격자가 0이 아닐때
        else:
            dice[-1] = board[nx][ny]
            board[nx][ny] = 0
    
        print(dice[0])

     

    느낀 점

    아이디어 한번 잘못 생각하고 코드까지 다 구현하면 돌아가기가 힘들다는 것을 깨달았습니다.

    이 아이디어 구현하는데 집중력을 다 써서 다른 방법을 떠올리기가 쉽지 않았습니다.

    아이디어가 확실한지 반례는 없는지 확인까지 다 해보고 그다음에 코드 구현을 들어가야 겠다고 느꼈습니다.

    아래 코드는 제가 구현했다가 1번 예제부터 안나와서 주석처리한 코드입니다..

    # import sys
    # input = sys.stdin.readline
    #
    # n, m, x, y, k = map(int, input().split())
    #
    # # 격자
    # graph = [list(map(int, input().split())) for _ in range(n)]
    # # 이동할 방향 리스트
    # moves = list(map(int, input().split()))
    #
    # # 윗면 기준 다음 방향으로 이동했을 때 밑면
    # dice_direction = {
    #     1 : [0,3,4,2,5],
    #     2 : [0,3,4,6,1],
    #     3 : [0,6,1,2,5],
    #     4 : [0,5,2,1,6],
    #     5 : [0,3,4,1,6],
    #     6 : [0,3,4,5,2]
    # }
    #
    # # 현재 주사위 눈금 현황
    # current_dice = {
    #     1 : 0,
    #     2 : 0,
    #     3 : 0,
    #     4 : 0,
    #     5 : 0,
    #     6 : 0
    # }
    #
    # # 동, 서, 북, 남
    # dy = [100000, 0, 0, -1, 1]
    # dx = [100000, 1, -1, 0, 0]
    #
    #
    # def moving_dice(move):
    #     global current_top
    #     global y
    #     global x
    #
    #     print(current_dice)
    #     # 다음 좌표
    #     ny = y + dy[move]
    #     nx = x + dx[move]
    #
    #     # 벗어날 경우 아무동작도 하지 않음
    #     if not (0<=ny<n) and (0<=nx<m):
    #         return
    #
    #     # 이동 후 현재 밑면
    #     # print(dice_direction[current_top])
    #     # print(move)
    #
    #     # 현재 밑면 : 현재 윗면 기준으로 아랫면 구하기
    #     current_bottom = dice_direction[current_top][move]
    #     # print(f"current_top : {current_top}, move : {move}")
    #     # print(current_bottom)
    #     # print(f"current_top : {current_top}, current_bottom : {current_bottom}, y : {y}, x: {x}, ny : {ny}, nx : {nx}, move : {move}")
    #     # print("현재 주사위의 눈금")
    #
    #
    #     # 격자가 0이 아닐 경우
    #     if graph[ny][nx] != 0:
    #         # 주사위의 밑면을 격자로 복사한 후
    #         current_dice[current_bottom] = graph[ny][nx]
    #         # 격자는 0으로 만든다.
    #         graph[ny][nx] = 0
    #     # 격자가 0일 경우
    #     else:
    #         # 주사위의 눈금이 격자로 복사된다.
    #         graph[ny][nx] = current_dice[current_bottom]
    #
    #     current_top = 7-current_bottom
    #     # print(f"current_top : {current_top}, current_bottom : {current_bottom}, y : {y}, x: {x}, ny : {ny}, nx : {nx}, move : {move}")
    #     y = ny
    #     x = nx
    #     print(current_dice[current_top])
    #
    # current_top = 1
    # for move in moves:
    #     moving_dice(move)

     

    참고한 블로그

    https://hongcoding.tistory.com/128

Designed by Tistory.