Notice
Recent Posts
Recent Comments
Today
Total
04-19 00:01
Archives
관리 메뉴

Jeongchul Kim

백준 삼성 코딩 기출 문제 - 주사위 굴리기 python 본문

Algorithm

백준 삼성 코딩 기출 문제 - 주사위 굴리기 python

김 정출 2019. 10. 17. 22:54

백준 삼성 코딩 기출 문제 - 주사위 굴리기 python



출처 : BAEKJOON ONLINE JUDGE

주사위 굴리기 (https://www.acmicpc.net/problem/14499)



문제 설명

지도의 크기 NXM에서 오른쪽은 동쪽, 위쪽은 북쪽입니다. 주사위가 하나 주어지는데 모든 면에는 0이 적혀져 있습니다. 주사위가 놓여진 좌표가 (x, y)가 있습니다. 지도의 각 칸에는 정수가 쓰여져 있고, 주사위를 굴리면 돌아가는데 이동한 칸 수에 0이면 주사위 바닥면에 쓰여 있는 수가 복사됩니다. 0이 아닌 경우에는 칸에 쓰여 있는 수가 바닥면으로 복사되고, 칸에 쓰여 있는 수는 0으로 교체가 됩니다. 명령이 주어지는대 동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어집니다.


복잡하게 생각하면 끝없이 복잡합니다. 주사위는 동(오른쪽) 서(왼쪽) 남(아래로) 북(위로)으로 회전이 되면서 인덱스가 변하게 됩니다.


주사위의 모든 면을 인덱스로 관리하면 접근하기 쉽습니다. 회전에 따라 인덱스가 움직이게 됩니다. 


 

문제 풀이

[1] 입력을 받습니다.

N, M, x, y, K = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(N)]
commands = list(map(int, input().split()))


[2] board에서 주사위의 위치인 x, y의 좌표 값을 관리해야 합니다. 움직이려는 방향에 따라서 x, y의 값이 변화합니다. 

dx, dy = (0, 0, -1, 1), (1, -1, 0, 0)


[3] 주사위의 처음 값과 주사위의 값을 임시적으로 저장하는 temp라는 변수를 놓습니다.

# 가장 처음에 주사위의 값은 0이 적혀 있습니다.
dice, temp = [0]*6, [0]*6


[4] 위에서 복잡하게 설명한 방향에 따른 인덱스입니다.

회전에 따라 기존에 지정한 인덱스에 변하는 인덱스 값을 넣습니다.

원래 인덱스는 (0, 1, 2, 3, 4, 5) 이고, 동쪽 회전을 예로 들면 0의 자리에 2가 오게되고, 1의 자리에 0이 오게 되고, 바닥에 해당하는 5에 1이 오게 됩니다. 따라서 동쪽은 (2, 0, 5, 3, 4, 1) 표현됩니다. 

# 주사위의 현재 인덱스를 정합니다.
direction = [
    (2, 0, 5, 3, 4, 1), # 동쪽
    (1, 5, 0, 3, 4, 2), # 서쪽
    (4, 1, 2, 0, 5, 3), # 북쪽
    (3, 1, 2, 5, 0, 4) # 남쪽
]


[5] 자 이제 들어온 command 순서에 따라서 시뮬레이션 해주면 됩니다. direction 인덱스 리스트 관리를 위해 command에 -1빼고 시작합니다.

[6] 주사위의 위치를 나타내는 (x, y) 의 좌표가 command에 따라서 움직입니다. row 인덱스는 x, column 인덱스는 y에서 보고 있습니다. 따라서 동쪽으로 가야한다면 y가 1이 증가되야 합니다. 반대로 남쪽으로 내려가야된다면 x가 1이 증가 됩니다. 북쪽으로 올라가면 x가 -1이 됩니다.

[7] 주사위는 방향에 따라서 계속 굴러가지만 board 밖으로 나갈 수 없기 때문에 board보다 커지지 않도록 제한을 걸어 둡니다. 위에서 dx, dy를 더해서 업데이트 했기 때문에 원 상태로 돌리기 위해서 dx, dy 다시 뺍니다.  돌아가지 않으므로 주사위는 그대로 있기 때문에 아무런 출력이 없습니다. “문제의 조건인 바깥으로 이동시키려고 하는 경우에는 해당 명령을 무시해야 하며, 출력도 하면 안된다.” 이것을 만족하기 위해 continue 문을 쓰면 됩니다.

[8] 임시값으로 현재 주사위 값을 저장합니다.

[9] 방향 회전에 따른 주사위의 값을 저장합니다.

[10] 지도의 칸에 값이 있다면 바닥면에 칸의 값을 주사위에 저장하고, 칸은 0으로 업데이트 합니다.

[11] 칸이 0이라면, 주사위의 값을 복사합니다.

[12] 최종적으로 주사위의 바닥면을 출력합니다.

for command in commands:
    command -= 1
    x, y = x + dx[command], y + dy[command] # 움직이는 x, y좌표 구한다
    if x < 0 or x >= N or y < 0 or y >= M: # 맵보다 커지지 않도록 제한
        x, y = x - dx[command], y - dy[command] # 원래대로 x, y값 복구
        continue # 명령 무시, 출력 X
    for idx in range(6): # 임시값으로 현재 주사위값 저장
        temp[idx] = dice[idx]
    for idx in range(6): # 방향 회전에 따른 주사위값 저장
        dice[idx] = temp[direction[command][idx]]
    if board[x][y]: # 지도의 칸에 값이 있다면,
        dice[5] = board[x][y] # 바닥면에 칸의 값을 넣고
        board[x][y] = 0 # 칸은 0으로 업데이트
    else:
        board[x][y] = dice[5] # 칸 이 0이라면, 주사위의 값을 복사
    print(dice[0]) # 주사위의 바닥면을 출력


전체 코드

N, M, x, y, K = map(int, input().split())
board = [list(map(int, input().split())) for _ in range(N)]
commands = list(map(int, input().split()))
dx, dy = (0, 0, -1, 1), (1, -1, 0, 0)
# 가장 처음에 주사위의 값은 0이 적혀 있습니다.
dice, temp = [0]*6, [0]*6
# 주사위의 현재 인덱스를 정합니다.
direction = [
    (2, 0, 5, 3, 4, 1), # 동쪽
    (1, 5, 0, 3, 4, 2), # 서쪽
    (4, 1, 2, 0, 5, 3), # 북쪽
    (3, 1, 2, 5, 0, 4) # 남쪽
]
# 동쪽(오른쪽) 1, 서쪽 2, 북쪽(위쪽) 3, 남쪽 4
for command in commands:
    command -= 1
    x, y = x + dx[command], y + dy[command] # 움직이는 x, y좌표 구한다
    if x < 0 or x >= N or y < 0 or y >= M: # 맵보다 커지지 않도록 제한
        x, y = x - dx[command], y - dy[command]
        continue
    for idx in range(6):
        temp[idx] = dice[idx]
    for idx in range(6):
        dice[idx] = temp[direction[command][idx]]
    if board[x][y]:
        dice[5] = board[x][y]
        board[x][y] = 0
    else:
        board[x][y] = dice[5]
    print(dice[0])


Comments