1일 1PS 77일차!

📚 문제


[골드 1] - 정육면체 전개도

💡 풀이 과정


  • 처음에는 2차원에 정육면체의 면들이 미리 정해질 줄 알았다.

밑 오 위 왼 밑 오 
뒤 ㅡ ㅡ ㅡ ㅡ ㅡ
위 ㅡ ㅡ ㅡ ㅡ ㅡ
앞 ㅡ ㅡ ㅡ ㅡ ㅡ
밑 ㅡ ㅡ ㅡ ㅡ ㅡ
뒤 ㅡ ㅡ ㅡ ㅡ ㅡ

  • 위와 같이 나열되고 6*6 입력에 맞춰 1인 부분이 6면을 나타내면 전개도라 생각했다.
  • 하지만 (1, 1) 위치에 있는 면은 출발 위치에 따라 다르게 설정된다.
    • “오” 에서 내려오면 “뒤”
    • “뒤” 에서 오른쪽으로 가면 “오”


  • 즉, DFS 를 통해 한칸씩 면을 결정해 나가며 출발한 면을 단서로 해당 면을 확정지어야한다.
  • 각 면에서 시계방향으로 접근 가능한 면들은 다음과 같다.

밑 = [앞, 오, 뒤, 왼]
오 = [앞, 위, 뒤, 밑]
왼 = [앞, 밑, 뒤, 위]
앞 = [위, 오, 밑, 왼]
뒤 = [밑, 오, 위, 왼]
위 = [앞, 왼, 뒤 ,오]

  • 각 면에서 접근할 수 있는 면의 순서는 동일하지만, 각 면에서의 offset 을 따로 구해주어야한다.
  • 이를 구하기 위해서는 (이전의 면, 이전의 면을 가르키는 방향, 다음 방향) 3가지가 필요하다.
    • ㅁㅁㅁ 이렇게 가로로 이어진 전개도를 예시로 들어보자.
    • 가장 처음 ㅁ 는 “밑”으로 규정되며 다음 ㅁ 는 “오” 로 설정되어있다 가정하자.
    • 밑-오-ㅁ 여기에서 3가지는 (“밑”, “<-“ (3), “->” (1)) 이다.
    • 즉, 현재 “오” 를 기준으로 “<-“ 를 의미하는 3번 인덱스가 “밑” 에 맞게 offset 이 구해져야한다는 뜻이다.
    • 위에서 오[3] = “밑” 이므로 여기에서는 offset = 0 이다.
    • 따라서 다음 칸은 오[1 + offset] 으로 “위” 를 뜻하는 것을 알 수 있다.
  • 6번의 과정을 거쳤을 때 [밑, 오, 왼, 뒤, 앞, 위] 가 중복 없이 모두 나타난다면 전개도가 생성된다는 뜻이다.

📌포인트


  • visited
    • visited[init_x][init_y] = True 를 해줘야한다.

💻 코드



from collections import deque

# 위부터 시계방향 순서..
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

# 각 전개도 기준 시계방향에 위치한 전개도들..
cube_loc = {
    "밑": ["앞", "오", "뒤", "왼"],
    "오": ["앞", "위", "뒤", "밑"],
    "왼": ["앞", "밑", "뒤", "위"],
    "앞": ["위", "오", "밑", "왼"],
    "뒤": ["밑", "오", "위", "왼"],
    "위": ["앞", "왼", "뒤", "오"]
}

# 가장 첫 "1" 을 찾아내는 함수
def findStart():
    for i in range(6):
        for j in range(6):
            if board[i][j] == 1:
                return (i, j)


def bfs():
    # 가장 첫 "1" 의 위치를 찾아낸다.
    init_x, init_y = findStart()

    queue = deque()
    queue.clear()
    queue.append([init_x, init_y, "밑", "앞", 2])
    cube = ["밑"]

    visited = [[False for _ in range(6)] for _ in range(6)]
    visited[init_x][init_y] = True

    while queue:
        x, y, now, prev, direction = queue.popleft()

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx < 0 or nx >= 6 or ny < 0 or ny >= 6 or visited[nx][ny] or board[nx][ny] == 0:
                continue

            visited[nx][ny] = True

            # cube_loc[now] 에서 (dir + 2) % 4 번쨰에 prev 가 나타나도록 변수 w 를 더해줘야한다.
            # cube_loc[now][w + (dir + 2) % 4] == prev
            a = cube_loc[now].index(prev)
            b = (direction + 2) % 4
            w = (a - b) % 4

            # 해당 위치의 블록을 구한다.
            current_block = cube_loc[now][(w + i) % 4]
            if current_block in cube:
                return "no"

            # 6면체의 전개도가 모두 구해졌으면 그대로 return 
            if len(cube) == 6:
                return "yes"
            else:
                cube.append(current_block)

            queue.append([nx, ny, current_block, now, i])

    return "yes"


for _ in range(3):
    board = [list(map(int, input().split())) for _ in range(6)]
    print(bfs())

업데이트:

댓글남기기