본문 바로가기

etc/자료구조와 알고리즘

BFS

BFS(Breadth First Search) 알고리즘은 '너비 우선 탐색'이라는 의미를 가진다. 이는 가까운 노드부터 탐색하는 알고리즘이다. BFS는 스택 자료구조를 사용하는 DFS와 달리 큐 자료구조를 이용한다. 이를 이용하면 먼저 들어온 것이 먼저 나가게 되어, 가까운 노트부터 탐색을 진행하게 된다.

 

BFS의 동작 과정은 다음과 같다.

  1. 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.
  2. 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리를 한다.
  3. 2번 과정을 더 이상 수행할 수 없을 때까지 반복한다. (즉, 큐가 빌때 까지)

 

bfs 구현 예시

from collections import deque


def bfs(graph, current_node, visited):
    q = deque([current_node])

    # 현재 노드를 방문 처리
    visited[current_node] = True

    # 큐가 빌 때까지 반복
    while q:
        # 큐에서 원소 하나 꺼냄
        v = q.popleft()
        print(v, end=' ')
        
        # 해당 원소 연결된 인접 노드들을 
        for adjacent_node in graph[v]:
            # 아직 방문하지 않았다면
            if not visited[adjacent_node]:
                # 큐에 삽입하고
                q.append(adjacent_node)
                # 방문처리
                visited[adjacent_node] = True


# 각 노드가 연결된 정보를 리스트 자료형으로 표현(2차원 리스트)
graph = [
  [],
  [2, 3, 8],
  [1, 7],
  [1, 4, 5],
  [3, 5],
  [3, 4],
  [7],
  [2, 6, 8],
  [1, 7]
]

# 각 노드가 방문된 정보를 리스트 자료형으로 표현(1차원 리스트)
visited = [False] * 9

# 정의된 BFS 함수 호출
bfs(graph, 1, visited)
1 2 3 8 7 4 5 6

 

 

이제 bfs 예제 문제를 보자.

 

문제

  • 공삼이는 N x M 크기의 직사각형 형태의 미로에 갇혀있다. 공삼이의 위치는 (1, 1)이고 미로의 출구는 (N, M)에 존재하며 한 번에 한 칸씩 이동할 수 있다. 괴물이 있는 부분은 0, 없는 부분은 1로 표시되어있다. 괴물을 피해서 탈출할기 위해 움직여야 하는 최소 칸의 개수를 구하시오. 칸을 셀 때는 시작 칸과 마지막 칸을 모두 포함해서 계산한다.

 

입력 조건

  • 첫째 줄에 두 정수 N, M(4 <= N, M <= 200)이 주어진다.
  • 다음 N개의 줄에는 각각 M개의 정수로 미로의 정보가 주어진다. 

 

ex)

3 3
110
010
011

 

 

BFS가 시작 지점에서 가까운 노트부터 차례대로 그래프의 모든 노드를 탐색하기 때문에 이런 유형의 문제를 해결하기에 효과적이다. (1, 1) 지점에서 모든 노드의 값을 거리 정보로 넣으면 된다.

 

from collections import deque


n, m = map(int, input().split())

graph = []
for _ in range(n):
    graph.append(list(map(int, input())))


def bfs(x, y):
    q = deque()

    # 탐색 시작 노드를 스택에 삽입
    q.append((x, y))
    
    while q:
        x, y = q.popleft()

        # 현재 위치에서 상하좌우 위치 확인
        for dx, dy in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
            nx = x + dx
            ny = y + dy

            # 공간을 벗어난 경우 무시
            if nx < 0 or nx >= n or ny < 0 or ny >= m:
                continue
            # 벽인 경우 무시
            if graph[nx][ny] == 0:
                continue
            # 처음 방문한 곳이면 거리 기록 -> 방문 처리이기도함
            if graph[nx][ny] == 1:
                graph[nx][ny] = graph[x][y] + 1
                # 큐에 삽입
                q.append((nx, ny))
    
    # 가장 오른쪽 아래까지의 최단 거리 반환
    return graph[n - 1][m - 1]

print(bfs(0, 0))

'etc > 자료구조와 알고리즘' 카테고리의 다른 글

정렬  (0) 2024.03.20
DFS  (0) 2024.03.19
재귀 함수  (0) 2024.03.19
스택/큐  (0) 2024.03.19