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을 출력한다.
from collections import deque
import sys
input = sys.stdin.readline
n, m = map(int,input().split())
maze = []
for _ in range(n):
maze.append(list(map(int,input().strip())))
# 상하좌우 정의
dx = [-1,1,0,0]
dy = [0,0,-1,1]
def solve_problem():
visited =[[[0]*2 for _ in range(m)] for _ in range(n)]
q = deque()
q.append((0,0,0))
visited[0][0][0] = 1
while q:
x,y,z = q.popleft()
if x == m-1 and y == n-1:
return visited[y][x][z]
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < m and 0 <= ny < n:
# 방문하지 않았고, 현지 위치에서 이동이 가능하다면
if maze[ny][nx] == 0 and visited[ny][nx][z] == 0:
visited[ny][nx][z] = visited[y][x][z] + 1
q.append((nx,ny,z))
elif maze[ny][nx] == 1 and z ==0:
visited[ny][nx][z+1] = visited[y][x][z] + 1
q.append([nx,ny,z+1])
return -1
print(solve_problem())
해당 코드에서는 3차원 배열을 이용하여, 벽을 뚫었을 때의 경우의 수까지 계산하여 문제를 풀었다. 이를 이용하면 처음 벽을 뚫었을 때가 가장 빠른 경우의 수이므로 최소를 고려하지 않아도 되고. 그리고 가장 최단 경로를 찾을 수 있다. 또 가장 빨리 도달한 visited[x][y]가 가장 최단 경로이므로 먼저 도착하면 바로 return 해서 풀 수 있도록 하였다.
from collections import deque
import sys
input = sys.stdin.readline
n, m = map(int,input().split())
maze = []
for _ in range(n):
maze.append(list(map(int,input().strip())))
# 상하좌우 정의
dx = [-1,1,0,0]
dy = [0,0,-1,1]
def solve_problem():
visited =[[[0]*2 for _ in range(m)] for _ in range(n)]
q = deque()
q.append((0,0,0))
visited[0][0][0] = 1
while q:
x,y,z = q.popleft()
if x == m-1 and y == n-1:
return visited[y][x][z]
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < m and 0 <= ny < n:
# 방문을 하지 않고, 벽을 뚫지 않은 상태라면 벽을 뚫을 수 있다.
if visited[ny][nx][z] == 0 and z == 0 and maze[ny][nx] == 1:
visited[ny][nx][z+1] = visited[y][x][z] + 1
z += 1
q.append((nx,ny,z))
# 방문을 하지 않은 상태라면, 벽을 뚫고 난 후 상황이라면 벽을 뚫지 못하고 지나가야한다.
elif visited[ny][nx][z] == 0 and z == 1 and maze[ny][nx] == 0:
visited[ny][nx][z] = visited[y][x][z] + 1
q.append((nx,ny,z))
if visited[n-1][m-1][z] == 0:
return -1
print(solve_problem())
흐음 문제의 초점을 제대로 파악하지 못하고, 너무 제한 사항을 많이 걸어놓은 것이 흠이었다. 이렇게 하다보니까, 한 번 벽을 뚫자마자 다른 벽을 뚫을 수 있는 경우의 수 마저 줄여버렸다. 그래서 틀렸다.
후기
- BFS 문제하고 dfs 문제 진짜 많이 풀었다아아