문제
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을 출력한다.
예제 입력과 출력
알고리즘 분류
BFS
정답
from collections import deque
import sys
input = lambda : sys.stdin.readline().rstrip()
n,m=map(int,input().split())
a=[list(map(int,input())) for i in range(n)]
ch=[[[0,0] for j in range(m)] for i in range(n)]
dx=[-1,0,1,0]
dy=[0,1,0,-1]
def bfs():
de=deque()
de.append([0,0,0])
ch[0][0][0]= 1
while de:
x,y,z=de.popleft()
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < n and 0 <= ny < m:
if a[nx][ny] == 0 and ch[nx][ny][z] == 0:
ch[nx][ny][z] = ch[x][y][z] + 1
de.append([nx,ny,z])
elif a[nx][ny] == 1 and z == 0 and ch[nx][ny][z+1] == 0:
ch[nx][ny][z+1] = ch[x][y][z] +1
de.append([nx,ny,z+1])
bfs()
if ch[n-1][m-1][0] != 0 and ch[n-1][m-1][1] != 0: # 벽을 거친 경우와 거치지 않은 경우 둘 다 가능한 경우
print(min(ch[n-1][m-1][0],ch[n-1][m-1][1]))
elif ch[n-1][m-1][0] != 0: # 벽을 거치지 않은 경우만 가능한 경우
print(ch[n-1][m-1][0])
elif ch[n-1][m-1][1] != 0: #벽을 거친 경우만 가능한 경우
print(ch[n-1][m-1][1])
else: # 불가능한 경우
print(-1)
배열 ch를 x좌표, y좌료, 부순 것 개수로 3차원으로 만듭니다.
기본 BFS에서 벽이 나왔는데 벽을 뚫은 적이 없는 경우 세번째 차수 값을 바꿔 ch에 저장하고 그 값을 큐에 넣습니다.
한번 BFS를 수행하고 벽을 거쳤을 때와 거치지 않은 것 중 최단 거리를 구합니다.
백준 알고리즘 2206번 : www.acmicpc.net/problem/2206
'알고리즘 > 백준알고리즘' 카테고리의 다른 글
백준알고리즘 - 16194번 카드 구매하기 2 - 파이썬(Python) (0) | 2020.06.27 |
---|---|
백준알고리즘 - 11052번 카드 구매하기 - 파이썬(Python) (0) | 2020.06.27 |
백준알고리즘 - 4949번 균형잡힌 세상 - 파이썬(Python) (0) | 2020.06.25 |
백준알고리즘 - 10773번 제로 - 파이썬(Python) (0) | 2020.06.25 |
백준알고리즘 - 11055번 가장 큰 증가 부분 수열 - 파이썬(Python) (0) | 2020.06.24 |