◦ Algorithm/Python

백준 퍼즐 1525 BFS

밍블리s2 2023. 4. 4. 18:15

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

 

1525번: 퍼즐

세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

www.acmicpc.net

 

  • 2차원 배열 형태의 퍼즐을 문자열로 만들어준다는 것이 포인트!
  • 0의 위치를 바꿔나가면서 새로 생성된 그래프를 또다시 문자열로 만들어주고 "123456780"에 해당하는지 비교해줘야 함.
  • 2차원 배열에서의 x, y 좌표값은 문자열에서 index 값을 3으로 나눈 몫과 나머지로 구할 수 있음.

 

from collections import deque

graph = ""
for i in range(3):
    graph += "".join(list(input().split())) # 그래프를 문자열로 만들어준다 

queue = deque([graph])
visited = dict()    # key: 그래프, value: 해당 그래프를 만들기 위해 퍼즐을 옮긴 횟수 
dx = [1,-1,0,0]
dy = [0,0,-1,1]

def bfs():
    visited[graph] = 0

    while(queue):
        target = queue.popleft()

        if target == "123456780":
            return visited[target]
        
        idx = target.find("0")  # 그래프에서 빈 공간인 0의 위치
        x = idx // 3            # 2차원 배열일 때 빈 공간의 x 좌표
        y = idx % 3             # y 좌표

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

            if 0 <= nx < 3 and 0 <= ny < 3:
                n = nx * 3 + ny     # 0 주변의 퍼즐값 
                list_target = list(target) # 문자열 그래프를 리스트로 변환
                # swap
                # 빈 공간의 인덱스에 현재 좌표를 넣고 현재 좌표에 빈 공간의 인덱스 값을 넣는다.
                list_target[idx], list_target[n] = list_target[n], list_target[idx]
                new_target = "".join(list_target) # 리스트 퍼즐을 문자열로 변환

                # 현재 그래프 모양을 갖는 key 값이 없다면
                if not visited.get(new_target):
                    visited[new_target] = visited[target] + 1   # 횟수 갱신
                    queue.append(new_target)    # 탐색 추가

    # 탐색이 끝나도 정리된 상태가 안된다면 -1 리턴
    return -1

print(bfs())