[python]백준 14499 풀이

한상욱·2024년 1월 12일

[python]백준풀이모음

목록 보기
32/38
post-thumbnail

주사위 굴리기

백준 14499 문제 링크

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 이 지도의 위에 주사위가 하나 놓여져 있으며, 주사위의 전개도는 아래와 같다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다.

  2
4 1 3
  5
  6

주사위는 지도 위에 윗 면이 1이고, 동쪽을 바라보는 방향이 3인 상태로 놓여져 있으며, 놓여져 있는 곳의 좌표는 (x, y) 이다. 가장 처음에 주사위에는 모든 면에 0이 적혀져 있다.

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

주사위를 놓은 곳의 좌표와 이동시키는 명령이 주어졌을 때, 주사위가 이동했을 때 마다 상단에 쓰여 있는 값을 구하는 프로그램을 작성하시오.

주사위는 지도의 바깥으로 이동시킬 수 없다. 만약 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시해야 하며, 출력도 하면 안 된다.

입력

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다.

둘째 줄부터 N개의 줄에 지도에 쓰여 있는 수가 북쪽부터 남쪽으로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 주사위를 놓은 칸에 쓰여 있는 수는 항상 0이다. 지도의 각 칸에 쓰여 있는 수는 10 미만의 자연수 또는 0이다.

마지막 줄에는 이동하는 명령이 순서대로 주어진다. 동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어진다.

출력

이동할 때마다 주사위의 윗 면에 쓰여 있는 수를 출력한다. 만약 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시해야 하며, 출력도 하면 안 된다.

풀이

이 문제 역시도 구현 알고리즘으로 N, M의 범위가 작기 때문에 문제에서 요구하는 알고리즘을 구현하면 쉽게 해결할 수 있습니다.

먼저 각 명령에 따라서 다음 좌표의 값을 구할 수 있습니다. 해당 좌표가 지도를 벗어나게 된다면 명령을 무시해야 하므로 처음에는 명령에 의해 이동하는 칸이 이동할 수 있는 칸이지 판단하는 로직이 필요합니다. 이는 단순하게 조건문을 이용해서 쉽게 구현할 수 있습니다. 좌표가 하나라도 지도의 범위를 벗어나면 다음 명령으로 넘어갈 수 있도록 continue 해주면 됩니다.

이제 주사위가 굴러가야 합니다. 주사위를 기준으로 가장 위는 up, 아래는 bottom, 좌우상하는 각각 west, east, north, south 라고 하겠습니다. 좌우로 한칸 주사위가 굴러가면 north, south는 값이 변하지 않고, west, east, up, bottom의 값이 맞닿은 면에 따라서 한칸씩 이동하게 됩니다. 마찬가지로 상하로 움직이는 경우는 west, east가 고정되고 나머지 칸이 방향으로 한칸씩 이동하게 됩니다.

그리고 이동하게 됨에 따라서, 지도의 값이 0인지에 따라서 문제의 로직을 수행하면 되겠습니다.

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)]
command = list(map(int, input().split()))
# 주사위의 값을 저장하는 배열
dice = [0 for _ in range(7)]
# 주사위의 방향에 따른 값의 인덱스
up, north, east, west, south, bottom = 1, 2, 3, 4, 5, 6
for c in command:
    # 명령수행이 가능한가
    if c == 1:
        nx, ny = x, y+1
    elif c == 2:
        nx, ny = x, y-1
    elif c == 3:
        nx, ny = x-1, y
    else:
        nx, ny = x+1, y
	# 명령 수행이 불가능하다면 무시
    if nx < 0 or nx >= n or ny < 0 or ny >= m:
        continue

	# 명령에 따라서 주사위가 이동함
    if c == 1:
        tmp = east
        east = up
        up = west
        west = bottom
        bottom = tmp
    elif c == 2:
        tmp = west
        west = up
        up = east
        east = bottom
        bottom = tmp
    elif c == 3:
        tmp = north
        north = up
        up = south
        south = bottom
        bottom = tmp
    else:
        tmp = south
        south = up
        up = north
        north = bottom
        bottom = tmp
	
    # 지도의 값에 따라서 주사위의 밑면 혹은 지도의 값이 변경됨
    if graph[nx][ny] == 0:
        graph[nx][ny] = dice[bottom]
    else:
        dice[bottom] = graph[nx][ny]
        graph[nx][ny] = 0
	
    # 다음 주사위의 좌표 갱신
    x, y = nx, ny
    # 주사위의 상단의 값 출력
    print(dice[up])

저는 주사위의 값의 인덱스를 -1하고 싶지 않아서 일부러 7개의 배열을 선언하고 0번 인덱스를 사용하지 않았습니다.

profile
자기주도적, 지속 성장하는 모바일앱 개발자의 기록

0개의 댓글