[백준 삼성기출 O] 주사위 굴리기2(python)

이진규·2022년 10월 11일
1

백준(PYTHON)

목록 보기
109/115

문제

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

나의 코드

"""

"""

from collections import deque

N, M, K = map(int, input().split()) # N:세로크기, M:가로크기, K:이동횟수
pan = [ list(map(int, input().split())) for _ in range(N) ]
dice = [1, 2, 3, 4, 5, 6] # 인덱스 0 ~ 5 = 윗면 ~ 밑면

# 동, 남, 서, 북
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]

# 0. 가장 처음에 주사위 이동방향은 동쪽이고, 좌표는 (0, 0)이다.
x, y = 0, 0
d = 0
answer = 0

def dice_roll():
    global x, y, d

    mx = x + dx[d]
    my = y + dy[d]

    # 만약, 이동 방향에 칸이 없다면, 이동 방향을 반대로 한 다음 한 칸 굴러간다.
    if (0 <= mx < N and 0 <= my < M):
        x, y = mx, my # 좌표 업데이트
    else:
        if d == 0: d = 2
        elif d == 2: d = 0
        elif d == 1: d = 3
        elif d == 3: d = 1
        x += dx[d] # 좌표 업데이트
        y += dy[d]

    # 주사위 굴리기
    if d == 0: # 주사위의 이동방향이 동쪽
        dice[0], dice[2], dice[3], dice[5] = dice[3], dice[0], dice[5], dice[2]
    elif d == 1: # 주사위의 이동방향이 남쪽
        dice[0], dice[1], dice[4], dice[5] = dice[1], dice[5], dice[0], dice[4]
    elif d == 2: # 주사위의 이동방향이 서쪽
        dice[0], dice[2], dice[3], dice[5] = dice[2], dice[5], dice[0], dice[3]
    elif d == 3: # 주사위의 이동방향이 북쪽
        dice[0], dice[1], dice[4], dice[5] = dice[4], dice[0], dice[5], dice[1]

def dice_score():
    global answer

    visited = [ [False] * M for _ in range(N) ]
    visited[x][y] = True

    q = deque([(x, y)])
    C = 1 # 동서남북 으로 이동할 수 있는 칸의 수
    B = pan[x][y] # (x, y)에 있는 정수

    while q:
        px, py = q.popleft()

        for k in range(4):
            mx = px + dx[k]
            my = py + dy[k]

            if (0 <= mx < N and 0 <= my < M):
                if pan[mx][my] == B and not visited[mx][my]:
                    visited[mx][my] = True
                    C += 1
                    q.append((mx, my))

    answer += (B * C)


def dice_dir_choice():
    global d

    A = dice[5] # 주사위 아랫면
    B = pan[x][y] # (x, y)에 있는 정수

    if A > B:
        d = (d + 1) % 4
    elif A < B:
        d = (d - 1) % 4


for _ in range(K):

    # print(dice)

    # 1. 주사위가 이동 방향으로 한 칸 굴러간다. 만약, 이동 방향에 칸이 없다면, 이동 방향을 반대로 한 다음 한 칸 굴러간다.
    dice_roll()

    # print(x, y)
    # print(dice)

    # 2. 주사위가 도착한 칸 (x, y)에 대한 점수를 획득한다.
    dice_score()

    # print(answer)

    # 3. 주사위의 아랫면에 있는 정수 A와 주사위가 있는 칸 (x, y)에 있는 정수 B를 비교해 이동 방향을 결정한다.
    # 3-1. A > B인 경우 이동 방향을 90도 시계 방향으로 회전시킨다.
    # 3-2. A < B인 경우 이동 방향을 90도 반시계 방향으로 회전시킨다.
    # 3-3. A = B인 경우 이동 방향에 변화는 없다.
    dice_dir_choice()

print(answer)
    

설명

문제에서 설명한대로 방향 이동하는 것을 구현하고, 14499 주사위 굴리기 개념에 BFS 탐색만 추가하면 쉽게 풀 수 있다.

실제 시험에서도 이렇게만 출제되면 좋겠다!

참고 자료

profile
항상 궁금해하고 공부하고 기록하자.

0개의 댓글