새소식

Computer Science/코딩테스트 문제 풀이

[백준] [파이썬] [BFS] 2206번: 벽 부수고 이동하기

  • -

문제 보러 가기

 

연관 문제 보러 가기 -> 14442번: 벽 부수고 이동하기 2

 

문제

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다.

만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동하여도 된다.

한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.

맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.

출력

첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다.

예제 입력 1

6 4
0100
1110
1000
0000
0111
0000

예제 출력 1

15

예제 입력 2

4 4
0111
1111
1111
1110

예제 출력 2

-1


BFS문제는 이제 어느정도 유형에 완벽하게 익숙해졌다고 생각했는데 전혀 풀지 못하였다.

이문제를 여러본 보고 익숙해지자.

벽을 부수었는지 안부수었는지 체크해줄 칸을 만들어준다.

이전에는 방문을 했는지 안했는지만 x,y좌표값에 넣어주었다면, z값을 포함하여 벽을 부수었는지 안부수었는지 정보를 넣어줄 곳을 추가해준다.


import sys 
from collections import deque 

sys.stdin=open('input.txt', 'r')

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

if __name__=="__main__":
    N,M=map(int, input().split()) 
    board=[list(map(int, input())) for _ in range(N)]
    # visited[x][y]는 [0,0]에 대해 visited[x][y][0]은 방문 여부를 visited[x][y][1]은 벽파괴여부를 나타낸다
    visited = [[[0]*2 for _ in range(M)] for _ in range(N)] 
    visited[0][0][0]=1
    Q=deque() 
    Q.append((0,0,0))
    flag=0
    while Q:
        x,y,z=Q.popleft()
        if x==N-1 and y==M-1:
            print(visited[x][y][z])
            flag=1
            break 
        for i in range(4):
            nx=x+dx[i]
            ny=y+dy[i]
            if 0<=nx<N and 0<=ny<M:                                 # board 범위 안
                if board[nx][ny]==0 and visited[nx][ny][z]==0:      # 다음 이동할 곳이 벽이 아니고 이동 가능하며 아직 한번도 방문하지 않았다면 
                    visited[nx][ny][z] = visited[x][y][z]+1      # 이전 방문한 위치에서 걸린 시간 + 1    # 처음에는 z가 계속 0일것이다 
                    Q.append((nx,ny,z))
                elif board[nx][ny]==1 and z==0:                     # 만약 벽을 만났는데 아직까지 벽을 파괴하지 않았었다면 
                    visited[nx][ny][1] = visited[x][y][0]+1        # 이제는 벽을 파괴한 상태의 visited에 값을 업데이트 한다. 그리고 벽을 파괴 안했을때의 값 저장 위치는 멈춤 
                    Q.append((nx,ny,1))
    if flag==0:
        print(-1)
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.