[Alex] 데이터 장인의 블로그

[알고리즘] BFS (너비 우선 탐색) / DFS (깊이 우선 탐색) 본문

알고리즘

[알고리즘] BFS (너비 우선 탐색) / DFS (깊이 우선 탐색)

Alex, Yoon 2022. 7. 2. 18:36

개념 이해

그래프 탐색 : 어떤것들이 연속해서 이어질 때, 모두 확인하는 방법. 

Graph : Vertex(어떤 것) + Edge(이어지는 것)

[그래프 탐색 종류]

BFS : 너비 우선 탐색 (Breadth-first search)

기준 노드(Vertex)에서 자식 노드(Vertex) 부터 탐색하는 방법. 

즉, 주변에 분포해있는 노드부터 탐색하는 방법 (깊게 No, 넓게 Yes)

 

위의 그래프의 경우 탐색 차례 : 0 - 1 - 2 - 3 - 4 - 5 - 6 

BFS = Queue 자료형과 맞음

 

DFS : 깊이 우선 탐색 (Depth-first search)

기준 노드(Vertex)에서 자식 노드(Vertex) -> 자식노드까지 탐색하는 방법. 

즉, 자식의 자식까지(끝노드) 모두 탐색하는 방법  (깊게 Yes, 넓게 No)

 

위의 그래프의 경우 탐색 차례 : 0 - 1 - 3 - 4 - 2 - 5 - 6

DFS = Stack 자료형과 맞음

 

문제 풀이 [출처 : 백준] 

https://www.acmicpc.net/problem/1926

어떤 큰 도화지에 그림이 그려져 있을 때, 그 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하여라. 단, 그림이라는 것은 1로 연결된 것을 한 그림이라고 정의하자. 가로나 세로로 연결된 것은 연결이 된 것이고 대각선으로 연결이 된 것은 떨어진 그림이다. 그림의 넓이란 그림에 포함된 1의 개수이다.

 

요약하자면,

  • 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하는 문제
  • 모든 부분을 탐색해야 되기 때문에 BFS로 풀이
  • 이어져 있는 부분은 count 변수로 카운트해주고 paint 배열에 append
  • 그림의 개수는 len(paint), 가장 넓은 그림은 max(paint)

BFS로 이 문제를 푼다면

1. BFS 로 1의 위치를 찾는다. 

2. 이중 For문을 돌리면서 1이 나올때 BFS를 수행한다. 

2 - 1. 1이 있었던 좌표를 기준으로 (상, 하, 좌, 우) 차례대로 탐지를 해나간다. 만약 좌표 기준으로 주변에 1이 있는 경우는 count += 1 로 업데이트 후 0으로 변경. (확인 완료 표시)

2 - 2. 2-1에서 1로 탐지했던 좌표를 다음 탐지 대상으로 추가하기 위해서 Queue에 입력. 

from collections import deque

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

# 차례대로 
# 아래, 위, 오른쪽, 왼쪽 이동 좌표
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

def bfs(graph, a, b):
    queue = deque()
    queue.append((a, b))
    graph[a][b] = 0
    count = 1
 
    while queue:
        x, y = queue.popleft() # 큐의 특성인 '선입선출'을 표현하기 위해서 사용. 
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx < 0 or nx >= n or ny < 0 or ny >= m: # 더 이상 이동할 공간이 없는 경우는 제외하고 탐지.
                continue
            if graph[nx][ny] == 1:
                graph[nx][ny] = 0 # 기존의 graph 변수에서 확인을 마쳤다는 표시로 1 -> 0으로 변경
                queue.append((nx, ny))
                count += 1
    return count
 
paint = []
for i in range(n):
    for j in range(m):
        if graph[i][j] == 1:
            paint.append(bfs(graph, i, j))
 

if len(paint) == 0:
    print(len(paint))
    print(0)
else:
    print(len(paint))
    print(max(paint))

 

반응형
Comments