컴퓨터 공부/📚 Baekjoon(백준)

[백준/알고리즘/python/java] 14499번 - 주사위 굴리기

letzgorats 2022. 12. 12. 21:37

이미지를 누르면 문제 링크를 보실 수 있습니다.
이미지를 누르면 문제 링크를 보실 수 있습니다.
이미지를 누르면 문제 링크를 보실 수 있습니다.
이미지를 누르면 문제 링크를 보실 수 있습니다.

이 문제는 삼성sw 역량 테스트 기출 문제에 속하는데요. 삼성 코테 유형은 대체로 구현이 많이 나옵니다. 차근차근 문제를 이해하고 종이에 써가면서 풀어본다면, 끈기와 빨리 풀 수 있는 실력만 있다면 충분히 푸실 수 있는 문제입니다.

겉으로 봤을 땐, DFS나 BFS로 푸는 문제인 것 같지만, 단순 구현으로도 풀리는 문제입니다.

 

먼저 문제를 이해해보록할게요.

보드가 있구요. 보드 위에 주사위가 있습니다. 주사위는 보드 위 숫자가 0인 부분에 있고 명령에 따라서 굴리는 문제라고 보시면 됩니다.

그럼, 아래 문제의 내용이 이해가시나요?

주사위가 보드 위에서 굴려질 때마다 주사위 면에 적혀지는 숫자와 보드위에 적혀지는 숫자가 달라진다는 것을 알 수 있습니다. 즉, 주사위가 굴려짐에 따라 보드와 주사위의 숫자가 달라진다는 것이죠.

 

그렇다면, 주사위가 어느 방향으로 굴려질 때, 어떤 면이 어디로 오는지, 즉 주사위의 전개도에 따른 변화를 알아볼 필요가 있겠는데요, 복잡하지 않습니다.

구현의 특징은 그려보면 웬만해서는 다 해결이 돼요. 하지만, 모두가 미리 겁먹고 혹은 조금 더 효율적인 풀이가 있지는 않을까 하고 그러한 시도를 주저하게 되더라구요. 그러면 또, 시간은 가고 초조해지니까 그제서야 종이에 적어보면서 풀어보는데, 이미 시간은 흘렀겠죠..! 그러니까, 바로 종이에 그려보는 것을 주저하지 맙시다...!

각 명령은 (상,하,좌,우) 로 4가지 경우만 존재하므로, 각 명령에 따라 주사위 면의 숫자가 어디로 바뀌는지 갱신하면 됩니다. 

나머지 풀이는 코드를 토대로 설명드리겠습니다.

import sys
input = sys.stdin.readline

n, m, x, y, k = map(int,input().split())
# print(n,m,x,y,k)
board = []

for i in range(n):
    row = list(map(int,input().split()))
    board.append(row)
# print(graph)
cmd = list(map(int,input().split()))
# print(cmd)
dr = [0,0,-1,1] # 우 좌 상 하 (행)
dc = [1,-1,0,0] # 우 좌 상 하 (열)

dice = [0,0,0,0,0,0]    # 위 뒤 오른쪽 왼쪽 앞 아래

def go(cmd):
    
    a, b, c, d, e, f = dice[0],dice[1],dice[2],dice[3],dice[4],dice[5]

    if cmd == 1 :    # 동    
        dice[0],dice[1],dice[2],dice[3],dice[4],dice[5] = d,b,a,f,e,c

    elif cmd == 2:  # 서
        dice[0],dice[1],dice[2],dice[3],dice[4],dice[5] = c,b,f,a,e,d

    elif cmd == 3:  # 북
        dice[0],dice[1],dice[2],dice[3],dice[4],dice[5] = e,a,c,d,f,b
    
    elif cmd == 4:  # 남
        dice[0],dice[1],dice[2],dice[3],dice[4],dice[5] = b,f,c,d,a,e


nr, nc = x,y    # 시작 좌표
for i in cmd:
    # print(i)
    nr += dr[i-1]
    nc += dc[i-1]

    if nr < 0 or nr >= n or 0 > nc or nc >= m:
        nr -= dr[i-1]
        nc -= dc[i-1]
        continue
    go(i)
    if board[nr][nc] == 0:
        board[nr][nc] = dice[-1]
    else:
        dice[-1] = board[nr][nc]
        board[nr][nc] = 0

    print(dice[0])

문제에서 (동,서,북,남) 순으로 커맨드가 (1,2,3,4)이므로

(동,서,북,남) 순으로 행렬 이동 리스트 dr,dc를 만들어줍니다.

 

그러면 명령리스트 cmd를 돌 때, (각 명령 숫자-1)이 그 리스트의 방향이동 좌표가 됩니다.

예를 들어, 명령 커맨드가 "4"라면 남쪽으로 이동하라는 의미로, (4-1) = 3 번째 인덱스에 있는 방향이동을 수행하면 됩니다.

dr,dc의 3번째 인덱스는 각각 (1,0)므로, 행은 1증가, 열은 그대로 인 남쪽이동이라는 것을 알 수 있습니다.

이동한 좌표가 지도 NxM 범위 안에 들어온다면, go함수를 실행하고, 범위 밖이라면, 다시 좌표를 원상복구합니다.(이동불가하니까!)

 

go함수에서 이제 처음에 구상한 주사위의 전개도의 활약이 나옵니다.

각 4가지 경우에 따라 주사위 면이 어떻게 바뀔지 case를 나눠서 그대로 구현해줍니다.

 

이동을 완료한 주사위가 있는 바닥칸에 적혀져 있는 숫자가 0인지 아닌지에 따라 주사위의 아래쪽(dice[-1])과 보드에 적혀져 있는 숫자(board[nr][nc])가 달라지므로 해당 작업을 구현해줍니다. 바닥칸에 적혀져 있는 숫자가 0이라면 바닥칸을 주사위의 아래쪽에 적혀져 있는 숫자로 대체하고, 보드에 적혀져 있는 숫자가 0이 아니라면, 주사위 아래쪽(dice[-1])의 숫자를 보드에 적혀져 있는 숫자(board[nr][nc])로 대체하고 바닥면은 다시 0으로 갱신하면 됩니다.

 

전개도 부분만 직접 그려보면서, 구현하려고 차근차근 풀이한다면 충분히 푸실 수 있으실 겁니다! 저도 구현은 항상 힘들지만 힘내보자구요!

이상 주사위 굴리기를 정리해봤습니다.

반응형