BFS (Breadth First Search)
너비 우선 탐색
맹목적 탐색 방법 중 하나
시작 정점 방문하고 찾고자 하는 값을 찾을 때까지 시작노드와 인접한 노드들을 우선 방문하는 방법BFS의 특징
- 직관적이지 않다.
- 시작 노드를 기준으로 거리에 따라 단계별로 탐색하는 것이기 때문에 오해 발생 여지가 있다.- (DFS와 달리) 재귀적으로 동작하지 않는다.
- 반드시 그래프를 탐색하면서 어떤 노드를 방문했었는 지의 여부를 검사해야한다. (visited 변수)
- 무한루프에 빠질 위험이 있기 때문시간복잡도
인접 행렬 : ➡ |V|개의 노드에 대해 |V|개의 엣지 탐색
인접 그래프 : ➡ |V|개의 노드와 |E|개의 엣지 탐색
트리 혹은 그래프 탐색 문제여야 한다.
출발노드에서 목표노드까지의 최단 길이 경로를 보장한다.
경로가 매우 길 경우에는 탐색 가지가 급격히 증가함에 따라 많은 기억 공간을 필요로 하게 된다.
해가 존재하지 않는다면
유한 그래프(finite graph)의 경우 ➡ 모든 그래프를 탐색한 후에 실패로 끝난다.
무한 그래프(infinite graph)의 경우 ➡ 결코 해를 찾지도 못하고, 끝내지도 못한다.
두 노드 사이의 최단 경로 혹은 임의의 경로를 찾고 싶을 때
먼저 들어온 데이터를 먼저 탐색하는 방식(선입선출)이기 때문에, Queue를 사용하여 구현하는 것이 가장 바람직하다.
visit을 처리하는 과정에서 중복 탐색하는 경우가 없도록 꼼꼼히 살펴보도록 한다.
import sys
input = sys.stdin.readline
N = int(input())
map = []
for _ in range(N):
map.append(input().strip())
visit = [[0] * N for _ in range(N)]
group = []
def bfs_find_village(x, y):
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
queue = []
queue.append((x, y))
visit[x][y] = 1
house = 1
while queue:
a, b = queue.pop()
# (a, b)의 앞뒤양옆에 집이 있으면 queue에 추가
for i in range(4):
ax, by = a+dx[i], b+dy[i]
if 0 <= ax < N and 0 <= by < N \
and visit[ax][by] == 0 \
and map[ax][by] == '1':
queue.append((ax, by))
# (ax, by) 방문 처리, 집 수 +1
visit[ax][by] = 1
house += 1
return house
for i in range(N):
for j in range(N):
# 이전에 방문하지 않은 집들만 방문한다
if map[i][j] == '1' and not visit[i][j]:
# 단지 내 집 개수를 추가한다
# (i, j)와 인접한 집들을 찾아 visited 처리한다.
group.append(bfs_find_village(i, j))
print(len(group))
group.sort()
for i in group:
print(i)
미로는 최소 거리로 도달해야 하므로 bfs를 써야한다는 것은 자명하다.
반복문을 3중이나 썼으니 queue의 세번째 변수에 거리 값을 추가하여 중간에 for문을 없애는 것도 좋아보인다.
import sys
input = sys.stdin.readline
dx = [0, 0, 1, -1]
dy = [-1, 1, 0, 0]
N, M = map(int, input().split())
miro = []
for _ in range(N):
miro.append(input().strip())
visit = [[0] * M for i in range(N)]
queue = []
queue.append((0, 0))
visit[0][0] = 1
move = 1
while queue:
iter = len(queue)
move += 1
# depth를 기준으로 한 depth마다 for문을 새로 돌린다
for i in range(iter):
a, b = queue.pop(0)
# (a,b)의 앞뒤양옆 길로 가본다
for q in range(4):
ax, by = a+dx[q], b+dy[q]
# 구한 경우
if ax == N-1 and by == M-1:
print(move)
exit(0)
if 0 <= ax < N and 0 <= by < M \
and miro[ax][by] == '1' \
and not visit[ax][by]:
queue.append((ax, by))
visit[ax][by] = 1
<BAEKJOON: 실버 2> 촌수계산
<BAEKJOON: 실버 1> 그림
<BAEKJOON: 실버 1> 스타트링크
<BAEKJOON: 실버 1> 영역 구하기
<BAEKJOON: 실버 1> 안전 영역
<BAEKJOON: 골드 5> 적록색약
<BAEKJOON: 골드 4> 연구소
<BAEKJOON: 골드 4> 빙산
<BAEKJOON: 골드 3> 아기 상어
<BAEKJOON: 골드 1> 구슬 탈출 2