장 준
씨포유
장 준
전체 방문자
오늘
어제
  • 분류 전체보기 (91)
    • 프로그래밍언어 (15)
      • c언어 (10)
      • 파이썬 (0)
      • 자바스크립트 (5)
    • PS (58)
      • 알고리즘 이론 (18)
      • 프로그래머스 (5)
      • 백준 (35)
    • CS (16)
      • 자료구조 (5)
      • 운영체제 (3)
      • 네트워크 (5)
      • 데이터베이스 (0)
      • 기초 지식 (3)
    • 브랜드 (1)

블로그 메뉴

  • 태그

인기 글

태그

  • pypy3
  • recursion
  • bitmask
  • BFS
  • CS
  • 알고리즘
  • Network
  • DP
  • 프로그래밍언어
  • JS
  • 씨포유
  • nodejs
  • PS
  • Kruskal algorithm
  • 프로그래머스
  • 백준
  • python3
  • 자료구조
  • Priority Queue
  • 코딩테스트
  • DFS
  • 자바스크립트
  • Visual Studio
  • C
  • Stack
  • 기초 지식
  • JavaScript
  • Implementation
  • 파이썬
  • codesandbox

최근 댓글

최근 글

hELLO · Designed By 정상우.
장 준

씨포유

[백준(BOJ)] #1525- 퍼즐 (파이썬, PyPy3)
PS/백준

[백준(BOJ)] #1525- 퍼즐 (파이썬, PyPy3)

2022. 11. 3. 11:48
728x90

문제

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

 

1525번: 퍼즐

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

www.acmicpc.net

 


문제 풀이

BFS 알고리즘 적용하여 해결

 

1) 입력받은 board를 문자열로 변환

2) 완성된 퍼즐 모양이 나올 때까지 문자열의 인덱스를 조정해가면서 탐색. 퍼즐 모양이 나오면 움직인 횟수를 출력하고 퍼즐 모양을 만들 수 없으면 -1 출력

 

위와 같은 모양의 board에서 빈칸(0)을 움직이면서 퍼즐을 완성시키는 것이 목적입니다. BFS 알고리즘을 적용하여 퍼즐을 완성시키기 위해 2차원 모양의 board를 문자열로 변환시킵니다.

 

순서에 맞게 문자열로 변환시키면 문자열은 "103425786"이 됩니다.

 

완성된 퍼즐 모양은 좌측 상단의 그림 모양과 같고, 이를 문자열로 나타내면 "123456780"입니다. 문자열 "103425786"을 "123456780"으로 바꿔주면 되는 것입니다. 1차원 모양의 문자열과 2차원 모양의 board의 인덱스를 고려하여 움직일 수 있습니다.

 

뭔가 규칙이 보이시나요? 

 

1차원 문자열에서의 인덱스를 3으로 나눈 몫이 2차원 board에서의 행이 되고, 3으로 나눈 나머지가 열이 됩니다. 이를 반대로 하면 2차원 board에서 행 x 3 + 열이 1차원 문자열에서의 인덱스가 되는 것이죠.

 

문자열 -> board

행: index // 3
열: index % 3

board -> 문자열

인덱스: 3 * 행 + 열

 

이 원리를 사용하여 나올 수 있는 퍼즐 모양을 탐색하고, "123456780"모양의 퍼즐이 나오게 되면 움직인 횟수를 출력하고 종료합니다. 

 


구현

코드

import sys
from collections import deque
input = sys.stdin.readline

# 시작 위치 반환
def get_list_to_str(board):
    s = ''
    for i in range(3):
        for j in range(3):
            s += board[i][j]
    return s

def bfs(board):
    dx = [-1, 0, 1, 0]
    dy = [0, 1, 0, -1]

    # 완성된 퍼즐 모양
    target = '123456780'
    puzzle_set = set()
    dq = deque()

    dq.append((board, 0))
    puzzle_set.add(board)

    while dq:
        board, cnt = dq.popleft()
        # 퍼즐이 완성되면 횟수 반환
        if board == target:
            return cnt

        z = board.index('0')
        # 2차원 board에서 0이 있는 인덱스 
        tx = z // 3
        ty = z % 3

        for k in range(4):
            x = tx + dx[k]
            y = ty + dy[k]
            if 0 <= x < 3 and 0 <= y < 3:
                # 1차원 인덱스로 변환하여 0의 자리를 교체
                nz = 3 * x + y
                nboard = list(board)
                nboard[z], nboard[nz] = nboard[nz], nboard[z]
                nboard = "".join(nboard)

                # 이미 탐색한 퍼즐 모양이라면 큐에 넣지 않음
                if nboard not in puzzle_set:
                    dq.append((nboard, cnt + 1))
                    puzzle_set.add(nboard)
    # 퍼즐을 완성시키지 못하는 경우 -1 반환
    return -1


if __name__ == "__main__":
    board = [list(input().split()) for _ in range(3)]
    board = get_list_to_str(board)
    print(bfs(board))

 

결과

728x90
반응형
저작자표시 (새창열림)

'PS > 백준' 카테고리의 다른 글

[백준(BOJ)] #1562- 계단 수 (파이썬, PyPy3)  (0) 2022.11.08
[백준(BOJ)] #10844- 쉬운 계단 수 (파이썬, PyPy3)  (0) 2022.11.07
[백준(BOJ)] #1103- 게임 (파이썬, PyPy3)  (0) 2022.11.02
[백준(BOJ)] #1194- 달이 차오른다, 가자. (파이썬, PyPy3)  (2) 2022.10.30
[백준(BOJ)] #1655- 가운데를 말해요 (파이썬, PyPy3)  (0) 2022.10.20
    'PS/백준' 카테고리의 다른 글
    • [백준(BOJ)] #1562- 계단 수 (파이썬, PyPy3)
    • [백준(BOJ)] #10844- 쉬운 계단 수 (파이썬, PyPy3)
    • [백준(BOJ)] #1103- 게임 (파이썬, PyPy3)
    • [백준(BOJ)] #1194- 달이 차오른다, 가자. (파이썬, PyPy3)
    장 준
    장 준
    C4U(Computer For You)

    티스토리툴바