[파이썬] 백준 9944번 NxM 보드 완주하기

작성:

백준 #9944 NxM 보드 완주하기


  • 이 문제는 입력의 끝이 미리 주어지지 않기 때문에 더이상 입력 값이 없을 때 반복문에서 빠져나올 수 있도록 해야한다.
  • print만으로는 디버깅하기 힘들어서 텍스트 파일로 저장해서 살펴보며 디버깅했다.
    • print로 했을 때는 출력 값이 너무 많아서 처음에 함수가 어떻게 동작하는지 보기 힘들었다.


# 4방향
# 장애물, 보드의 경계, 이미 공이 지나갔던 곳 전까지 계속 이동
# 공이 더이상 이동할 수 없을 때 끝남
# 모든 빈 칸을 공이 방문해야함
# 최소 이동 횟수는 1000000개를 넘지 않는다.

# 출력: 모든 빈 칸을 방문하는 최소 이동 횟수 ('Case 1: 숫자')

# 최솟값을 구하므로 백트래킹 하고 가지치기 할 수 있을 것
# 모든 가능한 좌표에서 시작하여 백트래킹
# 최소 이동 횟수를 1000001로 두고 백트래킹을 모두 마친 후에도 그대로면 -1로.

import sys
sys.setrecursionlimit(1000001)

def BT(y, x, val):
    global move, N, M, left
    if val >= move: return

    changed = []

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

        while 0 <= ny < N and 0 <= nx < M and field[ny][nx] == '.':
            field[ny][nx] = '&'
            left -= 1
            changed.append((ny, nx))
            ny += dy[i]
            nx += dx[i]
        
        # with open('./example.txt', 'a') as f:
        #     f.write(f'y: {y}, x: {x}\n')
        #     f.write(f'{ny - dy[i]}, {nx - dx[i]}, {i}\n')
        #     f.write(f'left: {left}, changed: {len(changed)}\n')
        #     for _ in range(len(field)):
                # print(*field[_])
                # f.write(f'{field[_]}\n')
        # print(ny - dy[i], nx - dx[i], i)
        
        if changed:
            BT(ny - dy[i], nx - dx[i], val + 1)

        for _ in range(len(changed)):
            cy, cx = changed.pop()
            field[cy][cx] = '.'
            left += 1
    
    if not left:
        move = min(move, val)

start = 1
while True:
    try:
        N, M = map(int, input().split())
        left = 0
        field = [['.' for i in range(M)] for j in range(N)]
        
        for i in range(N):
            inp = list(input())
            for j in range(len(inp)):
                if inp[j] == '*': field[i][j] = '*'
                else: left += 1

        dy = [0, 1, 0, -1]
        dx = [1, 0, -1, 0]
        move = 1000001

        for i in range(N):
            for j in range(M):
                if field[i][j] == '.':
                    field[i][j] = '&'
                    left -= 1
                    BT(i, j, 0)
                    field[i][j] = '.'
                    left += 1

        if move == 1000001: move = -1
        
        print('Case {0}: {1}'.format(start, move))
        start += 1
    except EOFError:
        break

댓글남기기