본문 바로가기

프로그래밍/문제풀이

[Python] 백준 23288 주사위 굴리기 2

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

 

23288번: 주사위 굴리기 2

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다. 가장 왼

www.acmicpc.net

 

# 23288 주사위 굴리기 2

def move_dice(cur_dir):
    # 위로 이동
    if cur_dir == 0:
        temp_num = dice[0][1]
        dice[0][1] = dice[1][1]
        dice[1][1] = dice[2][1]
        dice[2][1] = dice[3][1]
        dice[3][1] = temp_num

    # 왼쪽으로 이동
    elif cur_dir == 1:
        temp_num = dice[1][1]
        dice[1][1] = dice[1][2]
        dice[1][2] = dice[3][1]
        dice[3][1] = dice[1][0]
        dice[1][0] = temp_num

    # 아래쪽으로 이동
    elif cur_dir == 2:
        temp_num = dice[0][1]
        dice[0][1] = dice[3][1]
        dice[3][1] = dice[2][1]
        dice[2][1] = dice[1][1]
        dice[1][1] = temp_num

    # 오른쪽으로 이동
    elif cur_dir == 3:
        temp_num = dice[1][1]
        dice[1][1] = dice[1][0]
        dice[1][0] = dice[3][1]
        dice[3][1] = dice[1][2]
        dice[1][2] = temp_num

    return

# 상 좌 하 우
dr = [-1, 0, 1, 0]
dc = [0, -1, 0, 1]

N, M, K = map(int, input().split())
grounds = [list(map(int, input().split())) for _ in range(N)]
dice = [
    [0, 2, 0],
    [4, 1, 3],
    [0, 5, 0],
    [0, 6, 0]
]

cur_r = 0
cur_c = 0
cur_dir = 3
total_score = 0

for _ in range(K):
    # 1. 주사위가 이동 방향으로 한 칸 굴러간다.
    tr = cur_r + dr[cur_dir]
    tc = cur_c + dc[cur_dir]
    if 0 <= tr < N and 0 <= tc < M:
        pass
    # 1-1. 만약 이동 방향에 칸이 없다면, 이동 방향을 반대로 한 다음 한 칸 굴러간다.
    else:
        cur_dir = (cur_dir + 2) % 4
        tr = cur_r + dr[cur_dir]
        tc = cur_c + dc[cur_dir]

    cur_r = tr
    cur_c = tc
    # 주사위도 이동시킨다.
    move_dice(cur_dir)
    # 2. 주사위가 도착한 칸 (x, y)에 대한 점수를 획득한다.
    temp_score = 0
    visited = [[0] * M for _ in range(N)]
    visited[cur_r][cur_c] = 1
    my_num = grounds[cur_r][cur_c]
    queue = [[cur_r, cur_c]]
    cnt = 1
    while queue:
        qr, qc = queue.pop(0)
        for i in range(4):
            cr = qr + dr[i]
            cc = qc + dc[i]
            if 0 <= cr < N and 0 <= cc < M and visited[cr][cc] == 0 and grounds[cr][cc] == my_num:
                visited[cr][cc] = 1
                queue.append([cr, cc])
                cnt += 1

    total_score += (my_num * cnt)

    # 3. 주사위의 아랫면에 있는 정수 A와 x, y에 있는 B를 비교해 이동 방향을 결정한다.
    A = dice[3][1]
    B = grounds[cur_r][cur_c]
    # 3-1. A > B인 경우 이동 방향 90도 시계 방향 회전
    if A > B:
        cur_dir = (cur_dir - 1) % 4
    # 3-2. A < B인 경우 90도 반시계방향
    elif A < B:
        cur_dir = (cur_dir + 1) % 4
    # 3-3. A == B인 경우 변화 X


print(total_score)

 

 

 

예전 코드

 

# 23288 주사위 굴리기 2

# 상 좌 하 우
dr = [-1, 0, 1, 0]
dc = [0, -1, 0, 1]


# 반대 방향
def change_dir(cur_dir):
    if cur_dir >= 2:
        cur_dir -= 2
    else:
        cur_dir += 2
    return cur_dir


# 동쪽
def move_right():
    temp = dice[1][1]
    dice[1][1] = dice[1][0]
    dice[1][0] = dice[3][1]
    dice[3][1] = dice[1][2]
    dice[1][2] = temp


# 서쪽
def move_left():
    temp = dice[1][1]
    dice[1][1] = dice[1][2]
    dice[1][2] = dice[3][1]
    dice[3][1] = dice[1][0]
    dice[1][0] = temp


# 북쪽
def move_up():
    temp = dice[1][1]
    dice[1][1] = dice[2][1]
    dice[2][1] = dice[3][1]
    dice[3][1] = dice[0][1]
    dice[0][1] = temp


# 남쪽
def move_down():
    temp = dice[1][1]
    dice[1][1] = dice[0][1]
    dice[0][1] = dice[3][1]
    dice[3][1] = dice[2][1]
    dice[2][1] = temp


def cal_score(B):
    queue = [cur_pos]
    visited = [[0] * M for _ in range(N)]
    visited[cur_pos[0]][cur_pos[1]] = 1
    cnt = 1
    while queue:
        qr, qc = queue.pop(0)
        for i in range(4):
            cr = qr + dr[i]
            cc = qc + dc[i]
            if 0 <= cr and cr < N and 0 <= cc and cc < M and visited[cr][cc] == 0 and grounds[cr][cc] == B:
                cnt += 1
                visited[cr][cc] = 1
                queue.append([cr, cc])

    return cnt * B


def move():
    global cur_dir
    # 범위 밖으로 벗어난다면 반대 방향으로
    # 맨 윗줄이면서 북쪽으로 간다면
    if cur_pos[0] == 0 and cur_dir == 0:
        cur_dir = change_dir(cur_dir)

    # 맨 아랫줄이면서 남쪽으로 간다면
    elif cur_pos[0] == N - 1 and cur_dir == 2:
        cur_dir = change_dir(cur_dir)

    # 맨 왼쪽이면서 서쪽으로 간다면
    elif cur_pos[1] == 0 and cur_dir == 1:
        cur_dir = change_dir(cur_dir)

    # 맨 오른쪽이면서 동쪽으로 간다면
    elif cur_pos[1] == M - 1 and cur_dir == 3:
        cur_dir = change_dir(cur_dir)
    cur_pos[0] += dr[cur_dir]
    cur_pos[1] += dc[cur_dir]

    # 주사위 이동
    # 동쪽
    if cur_dir == 3:
        move_right()
    # 북쪽
    elif cur_dir == 0:
        move_up()
    # 서쪽
    elif cur_dir == 1:
        move_left()
    # 남쪽
    elif cur_dir == 2:
        move_down()

    # 칸 점수 획득
    B = grounds[cur_pos[0]][cur_pos[1]]
    num = cal_score(B)
    score[0] += num
    return B


N, M, K = map(int, input().split())
grounds = [list(map(int, input().split())) for _ in range(N)]
cur_pos = [0, 0]
cur_dir = 3  # 북 서 남 동, 0, 1, 2, 3
dice = [[0] * 3 for _ in range(4)]
dice[0][1] = 2
dice[1][0] = 4
dice[1][1] = 1
dice[1][2] = 3
dice[2][1] = 5
dice[3][1] = 6

score = [0]
for _ in range(K):
    B = move()
    # 주사위 아랫면, 칸 점수 비교
    if dice[3][1] > B:
        # 90도 시계방향 회전
        cur_dir -= 1
        if cur_dir < 0:
            cur_dir += 4
    elif dice[3][1] < B:
        # 90도 반시계방향 회전
        cur_dir += 1
        if cur_dir >= 4:
            cur_dir -= 4

print(score[0])