์ด๊ฒ์ด ์ทจ์ ์ ์ํ ์ฝ๋ฉํ ์คํธ๋ค with ํ์ด์ฌ
5์ฅ. DFS/BFS
1. ์๋ฃ๊ตฌ์กฐ ๊ธฐ์ด
ํ์(Search) : ๋ง์ ์์ ๋ฐ์ดํฐ ์ค์์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๋ ๊ณผ์
์๋ฃ๊ตฌ์กฐ(Data Structure) : ๋ฐ์ดํฐ๋ฅผ ํํํ๊ณ ๊ด๋ฆฌํ๊ณ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๊ตฌ์กฐ
- ์ฝ์ (Push) : ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ๋ค
- ์ญ์ (Pop) : ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ค
์คํ(Stack)
- ์ ์ ํ์ถ(FILO) / ํ์ ์ ์ถ(LIFO)
- append() : ๋ฆฌ์คํธ์ ๊ฐ์ฅ ๋ค์ชฝ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
- pop() : ๋ฆฌ์คํธ์ ๊ฐ์ฅ ๋ค์ชฝ์์ ๋ฐ์ดํฐ๋ฅผ ๊บผ๋ด์ค๋ค
stack = []
# ์ฝ์
(5) - ์ฝ์
(2) - ์ฝ์
(3) - ์ฝ์
(7) - ์ญ์ () - ์ฝ์
(1) - ์ฝ์
(4) - ์ญ์ ()
stack.append(5)
stack.append(2)
stack.append(3)
stack.append(7)
stack.pop()
stack.append(1)
stack.append(4)
stack.pop()
print(stack) # ์ตํ๋จ ์์๋ถํฐ ์ถ๋ ฅ
print(stack[::-1]) #์ต์๋จ ์์๋ถํฐ ์ถ๋ ฅ
# ์ถ๋ ฅ
# [5, 2, 3, 1]
# [1, 3, 2, 5]
ํ(Queue)
- ์ ์ ์ ์ถ(First In First Out) ๊ตฌ์กฐ
- collections ๋ชจ๋์์ ์ ๊ณตํ๋ deque์๋ฃ๊ตฌ์กฐ ํ์ฉ
- deque๋ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๊ณ ๋นผ๋ ์๋๊ฐ ๋ฆฌ์คํธ ์๋ฃํ์ ๋นํด ํจ์จ์ ์ด๋ฉฐ queue ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ๋ ๊ฒ๋ณด๋ค ๊ฐ๋จํ๋ค.
from collections import deque
#ํ(Queue) ๊ตฌํ์ ์ํด deque ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
queue = deque()
# ์ฝ์
(5) - ์ฝ์
(2) - ์ฝ์
(3) - ์ฝ์
(7) - ์ญ์ () - ์ฝ์
(1) - ์ฝ์
(4) - ์ญ์ ()
queue.append(5)
queue.append(2)
queue.append(3)
queue.append(7)
queue.popleft()
queue.append(1)
queue.append(4)
queue.popleft()
print(queue) # ๋จผ์ ๋ค์ด์จ ์์๋๋ก ์ถ๋ ฅ
queue.reverse() # ๋ค์ ์ถ๋ ฅ์ ์ํด ์ญ์์ผ๋ก ๋ฐ๊พธ๊ธฐ
print(queue) # ๋์ค์ ๋ค์ด์จ ์์๋ถํฐ ์ถ๋ ฅ
# ์ถ๋ ฅ
# deque([3, 7, 1, 4])
# deque([4, 1, 7, 3])
์ฌ๊ทํจ์(Recursive Function)
- ์๊ธฐ ์์ ์ ๋ค์ ํธ์ถํ๋ ํจ์
def recursive_function():
print('์ฌ๊ท ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.')
recursive_function()
recursive_function()
* ์ฌ๊ท ํจ์์ ์ข ๋ฃ ์กฐ๊ฑด
- if๋ฌธ์ด ์ข ๋ฃ ์กฐ๊ฑด ์ญํ ์ํ
- ๋ํ์ ์ธ ์ : ํฉํ ๋ฆฌ์ผ(Factorial)
def factorial_recursive(n):
if n <= 1: # n์ด 1์ดํ์ธ ๊ฒฝ์ฐ 1์ ๋ฐํ
return 1
# n! = n * (n - 1)๋ฅผ ๊ทธ๋๋ก ์ฝ๋๋ก ์์ฑํ๊ธฐ
return n * factorial_recursive(n - 1)
- ์ฌ๊ทํจ์๋ ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํ๋ ๊ฒ๊ณผ ๋น๊ตํ์ ๋ ๋์ฑ ๊ฐ๊ฒฐํ ํํ์ด๋ค
2. ํ์ ์๊ณ ๋ฆฌ์ฆ DFS/BFS
DFS(Depth-First Search)
- ๊น์ด ์ฐ์ ํ์์ด๋ผ๊ณ ๋ ๋ถ๋ฅด๋ฉฐ, ๊ทธ๋ํ์์ ๊น์ ๋ถ๋ถ์ ์ฐ์ ์ ์ผ๋ก ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค
- ๋ ธ๋(Node)์ ๊ฐ์ (Edge)์ผ๋ก ํํ๋๋ฉฐ ์ด๋ ๋ ธ๋๋ฅผ ์ ์ (Vertex)๋ผ๊ณ ๋ ๋งํ๋ค
- ๋ ๋ ธ๋๊ฐ ๊ฐ์ ์ผ๋ก ์ฐ๊ฒฐ๋์ด ์๋ค๋ฉด '๋ ๋ ธ๋๋ ์ธ์ ํ๋ค(Adjacent)'๋ผ๊ณ ํํํ๋ค
- ์คํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ด์ฉ
<๊ทธ๋ํ๋ฅผ ํํํ๋ ๋ฐฉ์>
* ์ธ์ ํ๋ ฌ(Adjacency Matrix) : 2์ฐจ์ ๋ฐฐ์ด๋ก ๊ทธ๋ํ์ ์ฐ๊ฒฐ ๊ด๊ณ๋ฅผ ํํํ๋ ๋ฐฉ์
* ์ธ์ ๋ฆฌ์คํธ(Adjacency List) : ๋ฆฌ์คํธ๋ก ๊ทธ๋ํ์ ์ฐ๊ฒฐ ๊ด๊ณ๋ฅผ ํํํ๋ ๋ฐฉ์
- ์ธ์ ํ๋ ฌ ๋ฐฉ์์ ๋ชจ๋ ๊ด๊ณ๋ฅผ ์ ์ฅํ๋ฏ๋ก ๋ ธ๋ ๊ฐ์๊ฐ ๋ง์ ์๋ก ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถํ์ํ๊ฒ ๋ญ๋น๋๋ค
- ์ธ์ ๋ฆฌ์คํธ ๋ฐฉ์์ ์ฐ๊ฒฐ๋ ์ ๋ณด๋ง์ ์ ์ฅํ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ค
- ์ธ์ ๋ฆฌ์คํธ ๋ฐฉ์์ ์ธ์ ํ๋ ฌ ๋ฐฉ์์ ๋นํด ํน์ ํ ๋ ๋ ธ๋๊ฐ ์ฐ๊ฒฐ๋์ด ์๋์ง์ ๋ํ ์ ๋ณด๋ฅผ ์ป๋ ์๋๊ฐ ๋๋ฆฌ๋ค
<DFS ๋์ ๊ณผ์ >
1. ํ์ ์์ ๋ ธ๋๋ฅผ ์คํ์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค
2. ์คํ์ ์ต์๋จ ๋ ธ๋์ ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋ ธ๋๊ฐ ์์ผ๋ฉด ๊ทธ ์ธ์ ๋ ธ๋๋ฅผ ์คํ์ ๋ฃ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค. ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋ ธ๋๊ฐ ์์ผ๋ฉด ์คํ์์ ์ต์๋จ ๋ ธ๋๋ฅผ ๊บผ๋ธ๋ค.
3. 2๋ฒ์ ๊ณผ์ ์ ๋ ์ด์ ์ํํ ์ ์์ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
DFS ์์
- ์ฌ๊ท ํจ์ ์ด์ฉ์ ๊ฐ๊ฒฐํ๊ฒ ๊ตฌํ ๊ฐ๋ฅ
# DFS ๋ฉ์๋ ์ ์
def dfs(graph, v, visited):
# ํ์ฌ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
visited[v] = True
print(v, end=' ')
# ํ์ฌ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๋ค๋ฅธ ๋
ธ๋๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๋ฐฉ๋ฌธ
for i in graph[v]:
if not visited[i]:
dfs(graph, i, visited)
# ๊ฐ ๋
ธ๋๊ฐ ์ฐ๊ฒฐ๋ ์ ๋ณด๋ฅผ ๋ฆฌ์คํธ ์๋ฃํ์ผ๋ก ํํ(2์ฐจ์ ๋ฆฌ์คํธ)
graph = [
[],
[2, 3, 8],
[1, 7],
[1, 4, 5],
[3, 5],
[3, 4],
[7],
[2, 6, 8],
[1, 7]
]
# ๊ฐ ๋
ธ๋๊ฐ ๋ฐฉ๋ฌธ๋ ์ ๋ณด๋ฅผ ๋ฆฌ์คํธ ์๋ฃํ์ผ๋ก ํํ(1์ฐจ์ ๋ฆฌ์คํธ)
visited = [False] * 9
# ์ ์๋ DFS ํจ์ ํธ์ถ
dfs(graph, 1, visited)
# ์ถ๋ ฅ
# 1 2 7 6 8 3 4 5
BFS(Breadth First Search)
- ๋๋น ์ฐ์ ํ์
- ๊ฐ๊น์ด ๋ ธ๋๋ถํฐ ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ
- ์ ์ ์ ์ถ ๋ฐฉ์์ธ ํ ์๋ฃ๊ตฌ์กฐ ์ด์ฉ
<๋์ ๋ฐฉ์>
1. ํ์ ์์ ๋ ธ๋๋ฅผ ํ์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
2. ํ์์ ๋ ธ๋๋ฅผ ๊บผ๋ด ํด๋น ๋ ธ๋์ ์ธ์ ๋ ธ๋ ์ค์์ ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋๋ฅผ ๋ชจ๋ ํ์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
3. 2๋ฒ์ ๊ณผ์ ์ ๋ ์ด์ ์ํํ ์ ์์ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
BFS ์์
from collections import deque
# BFS ๋ฉ์๋ ์ ์
def bfs(graph, start, visited):
# ํ(Queue) ๊ตฌํ์ ์ํด deque ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
queue = deque([start])
# ํ์ฌ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
visited[start] = True
# ํ๊ฐ ๋น ๋๊น์ง ๋ฐ๋ณต
while queue:
# ํ์์ ํ๋์ ์์๋ฅผ ๋ฝ์ ์ถ๋ ฅ
v = queue.popleft()
print(v, end=' ')
# ํด๋น ์์์ ์ฐ๊ฒฐ๋, ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ์์๋ค์ ํ์ ์ฝ์
for i in graph[v]:
if not visited[i]:
queue.append(i)
visited[i] = 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
DFS | BFS | |
๋์ ์๋ฆฌ | ์คํ | ํ |
๊ตฌํ ๋ฐฉ๋ฒ | ์ฌ๊ท ํจ์ ์ด์ฉ | ํ ์๋ฃ๊ตฌ์กฐ ์ด์ฉ |
- 2์ฐจ์ ๋ฐฐ์ด์์์ ํ์ ๋ฌธ์ ๋ฅผ ๋ง๋๋ฉด ๊ทธ๋ํ ํํ๋ก ๋ฐ๊ฟ์ ์๊ฐํ๋ฉด ํ์ด๋ฐฉ๋ฒ์ ์กฐ๊ธ ๋ ์ฝ๊ฒ ๋ ์ฌ๋ฆด ์ ์๋ค
์ค์ ๋ฌธ์ 3. ์๋ฃ์ ์ผ๋ ค๋จน๊ธฐ
- DFS๋ก ํด๊ฒฐ
1) ํน์ ํ ์ง์ ์ ์ฃผ๋ณ ์, ํ, ์ข, ์ฐ๋ฅผ ์ดํด๋ณธ ๋ค์ ์ฃผ๋ณ ์ง์ ์ค์์ ๊ฐ์ด '0'์ด๋ฉด์ ์์ง ๋ฐฉ๋ฌธํ์ง ์์ ์ง์ ์ด ์๋ค๋ฉด ํด๋น ์ง์ ์ ๋ฐฉ๋ฌธํ๋ค
2) ๋ฐฉ๋ฌธํ ์ง์ ์์ ๋ค์ ์,ํ,์ข,์ฐ๋ฅผ ์ดํด๋ณด๋ฉด์ ๋ฐฉ๋ฌธ์ ๋ค์ ์งํํ๋ฉด, ์ฐ๊ฒฐ๋ ๋ชจ๋ ์ง์ ์ ๋ฐฉ๋ฌธํ ์ ์๋ค
3) 1~2๋ฒ์ ๊ณผ์ ์ ๋ชจ๋ ๋ ธ๋์ ๋ฐ๋ณตํ๋ฉฐ ๋ฐฉ๋ฌธํ์ง ์์ ์ง์ ์ ์๋ฅผ ์ผ๋ค
# DFS ์ค์ ๋ฌธ์ 3 - ์๋ฃ์ ์ผ๋ ค๋จน๊ธฐ
N, M = map(int, input().split())
graph = []
for i in range(N):
graph.append(list(map(int, input())))
# DFS๋ก ํน์ ํ ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ๋ค์ ์ฐ๊ฒฐ๋ ๋ชจ๋ ๋
ธ๋๋ค๋ ๋ฐฉ๋ฌธ
def dfs(x, y):
# ์ข
๋ฃ์กฐ๊ฑด 1 : ์ฃผ์ด์ง ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ๊ฒฝ์ฐ์๋ ์ฆ์ ์ข
๋ฃ
if x < 0 or x >= N or y < 0 or y >= M:
return False
# ์ฑ๊ณต์กฐ๊ฑด
# ํ์ฌ ๋
ธ๋๋ฅผ ์์ง ๋ฐฉ๋ฌธํ์ง ์์๋ค๋ฉด
if graph[x][y] == 0:
# ํด๋น ๋
ธ๋ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
graph[x][y] = 1
# ์ํ์ข์ฐ ์์น ์ฌ๊ทํธ์ถ
dfs(x, y - 1) # ์ข
dfs(x, y + 1) # ์ฐ
dfs(x - 1, y) # ์
dfs(x + 1, y) # ํ
return True
# ์ข
๋ฃ์กฐ๊ฑด 2
return False
# ๋ชจ๋ ๋
ธ๋์ ๋ํ์ฌ ์๋ฃ์ ์ฑ์ฐ๊ธฐ
result = 0
for i in range(N):
for j in range(M):
if dfs(i, j):
print(dfs(i, j))
result += 1
print(result)
์ค์ ๋ฌธ์ 4. ๋ฏธ๋ก ํ์ถ
- BFS ๋ก ํด๊ฒฐ
1) ๋งจ ์ฒ์์ (1, 1)์ ์์น์์ ์์ํ๋ฉฐ, (1, 1)์ ๊ฐ์ ํญ์ 1์ด๋ผ๊ณ ๋ฌธ์ ์์ ์ธ๊ธ๋์ด ์๋ค
2) (1, 1) ์ขํ์์ ์,ํ,์ข,์ฐ๋ก ํ์์ ์งํํ๋ฉด ๋ฐ๋ก ์ ๋ ธ๋์ธ (1, 2) ์์น์ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๊ฒ๋๊ณ ์๋กญ๊ฒ ๋ฐฉ๋ฌธํ๋
(1, 2) ๋ ธ๋์ ๊ฐ์ 2๋ก ๋ฐ๊พธ๊ฒ ๋๋ค
3) BFS๋ฅผ ๊ณ์ ์ํํ๋ฉด ๊ฒฐ๊ณผ์ ์ผ๋ก ์ต๋จ ๊ฒฝ๋ก์ ๊ฐ๋ค์ด 1์ฉ ์ฆ๊ฐํ๋ ํํ๋ก ๋ณ๊ฒฝ๋๋ค
# BFS ์ค์ ๋ฌธ์ 4 - ๋ฏธ๋ก ํ์ถ
from collections import deque
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]
# BFS ์์ค์ฝ๋ ๊ตฌํ
def bfs(x, y):
# ํ ๊ตฌํ์ ์ํด deque ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
queue = deque()
queue.append((x, y))
# ํ๊ฐ ๋น ๋๊น์ง ๋ฐ๋ณต
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] == 0:
continue
# ํด๋น ๋
ธ๋๋ฅผ ์ฒ์ ๋ฐฉ๋ฌธํ๋ ๊ฒฝ์ฐ์๋ง ์ต๋จ ๊ฑฐ๋ฆฌ ๊ธฐ๋ก
if graph[nx][ny] == 1:
graph[nx][ny] = graph[x][y] + 1
queue.append((nx, ny))
# ๊ฐ์ฅ ์ค๋ฅธ์ชฝ ์๋๊น์ง์ ์ต๋จ๊ฑฐ๋ฆฌ ๋ฐํ
return graph[n - 1][m - 1]
print(bfs(0, 0))