미로탐색 - 2178
[Silver I] 미로 탐색 - 2178
분류
너비 우선 탐색(bfs), 그래프 이론(graphs), 그래프 탐색(graph_traversal)
문제 설명
N×M크기의 배열로 표현되는 미로가 있다.
1 | 0 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | 1 | 1 |
미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.
위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.
입력
첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
출력
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
풀이
먼저 예전에 BFS는 최단거리 일 때 풀어야 한다고 들은 적이 있어서 BFS로 시도를 계속 했지만 갑자기 드문 의문이 그럼 언제 DFS, BFS를 구분 해야하는 지…?
- DFS
- 검색 대상 그래프가 큰 경우(정점과 간선의 개수가 많은 경우)
- 경로의 특징을 저장해둬야 하는 문제[ ex) 각 정점에 숫자가 적혀있고 a부터 b까지 가는 경로를 구하는 데 경로에 같은 숫자가 있으면 안되는 문제]
- BFS는 경로의 특징을 가지지 못함
- BFS
- 미로찾기 등 최단거리를 구해야 할 경우
- DFS는 처음으로 발견되는 해답이 최단거리 보장을 못함
- BFS는 현재 노드에서 가까운 곳부터 찾기 때문에 경로 탐색 시 첫 번째로 찾아지는 해답이 곧 최단거리
- 미로찾기 풀이 흐름
- 미로의 정보를 담을 수 있는 graph list와 방문한 노드인지 check하는 visited list 선언
- 상, 하, 좌, 우를 바꿔가며 루트를 탐색하기 위해 현재의 위치에서 상,하,좌,우를 조정할 dx, dy list 선언
- bfs 탐색 시작 (deque 이용)
- 현재위치에서 상, 하, 좌,우 이동하며 이동한 위치가 invalid한 영역이거나, 벽에 가로 막히거나, 방문한 위치라면 다른 방향을 탐색하도록함
- 갈 수 있는 새로운 루투라면 이전에 방문 한 위치의 노드 값 + 1 즉 이동한 거리를 기록한 후 queue에 enqueue
- 다음에 방문 할 위치를 dequeue하여 상,하,좌,우 탐색 반복
코드
from collections import deque
def bfs(x, y):
# bfs 를 위한 deque
queue = deque()
# 처음 start 지점을 enqueue
queue.append((x, y))
# 처음 start 지점을 visited 처리
visited[0][0] = 1
# queue가 비어 있지 않는 동안 반복
while queue:
x, y = queue.popleft()
# 상, 하, 좌, 우 이동
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
# 상,하,좌,우 이동한 값이 invalid한 영역에 있는지 check
if nx >= N or nx < 0 or ny >= M or ny < 0:
continue
# 벽에 가로 막히는지 check
if graph[nx][ny] == 0:
continue
# 이미 방문한 노드인지 check
if visited[nx][ny] :
continue
# 갈 수 있는 길이라면
if graph[nx][ny] == 1:
# 이전에 방문 한 노드의 값 + 1 즉 이동한 거리
visited[nx][ny] = visited[x][y] + 1
queue.append((nx, ny))
return visited[N-1][M-1]
N, M = map(int, input().split())
graph = []
for i in range(N):
graph.append(list(map(int, input())))
# 상, 하, 좌, 우
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
visited = [[0 for _ in range(M)] for _ in range(N)]
print(bfs(0, 0))
댓글남기기