๐ ์ธ๊ณต์ง๋ฅ ํ์์๊ณ ๋ฆฌ์ฆ - ๋งน๋ชฉ์ ํ์ ์๊ณ ๋ฆฌ์ฆ
๐ 1. ๋งน๋ชฉ์ ํ์(Blind Search)์ด๋?
๋งน๋ชฉ์ ํ์(Blind Search)์ ํ์ ๊ณผ์ ์์ ๋ชฉํ ์ํ๊น์ง์ ๊ฑฐ๋ฆฌ๋ ๋น์ฉ์ ๊ณ ๋ คํ์ง ์๊ณ , ๋จ์ํ ๊ท์น์ ๋ฐ๋ผ ํ์์ ์งํํ๋ ๋ฐฉ์์
๋๋ค.
์ฆ, ํด๋ฆฌ์คํฑ(heuristic) ์ ๋ณด ์์ด ๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ฌด์์๋ก ํ์ํ๋ฉฐ ํด๊ฒฐ์ฑ
์ ์ฐพ์ต๋๋ค.
๐ ๋งน๋ชฉ์ ํ์์ ํน์ง
โ ์ฌ์ ์ ๋ณด ์์ด ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ํ์
โ ๋นํจ์จ์ ์ผ ์ ์์ผ๋, ์์ ํ์์ด ๋ณด์ฅ๋จ
โ ์ต์ ์ ํด๋ฅผ ๋ณด์ฅํ์ง ์์ (๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ต์ ๊ฒฝ๋ก๊ฐ ์๋ ์๋ ์์)
โ ๊ทธ๋ํ ๋๋ ํธ๋ฆฌ ๊ตฌ์กฐ์์ ์ฌ์ฉ๋จ
๐ ๋ํ์ ์ธ ๋งน๋ชฉ์ ํ์ ์๊ณ ๋ฆฌ์ฆ
1. ๊น์ด ์ฐ์ ํ์(DFS, Depth-First Search)
2. ๋๋น ์ฐ์ ํ์(BFS, Breadth-First Search)
3. ๊น์ด ์ ํ ํ์(DLS, Depth-Limited Search)
4. ๋ฐ๋ณต์ ๊น์ด ์ฌํ ํ์(IDDFS, Iterative Deepening DFS)
์ด์ ๊ฐ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ์ ํ๋์ฉ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ 2. ๊น์ด ์ฐ์ ํ์(DFS: Depth-First Search)
โ DFS๋?
DFS(๊น์ด ์ฐ์ ํ์, Depth First Search)๋ ํ ๊ฒฝ๋ก๋ฅผ ๋๊น์ง ํ์ํ ํ, ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ํ์ํ๋ ๋ฐฉ์์
๋๋ค.
์ฆ, ๋จผ์ ๊ฐ ์ ์๋ ๊ณณ๊น์ง ์ต๋ํ ๊น์ด ํ์ํ ํ, ๋งํ๋ฉด ๋๋์๊ฐ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ํ์ํ๋ ๋ฐฉ์์
๋๋ค.
์ด๋ฏธ์ง ์ถ์ฒ: ์ํค๋ฐฑ๊ณผ, '๊น์ด ์ฐ์ ํ์'
๐ DFS ๋์ ๊ณผ์
์์ ๋ ธ๋๋ฅผ ์คํ(Stack)์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
์คํ์ ์ต์๋จ ๋ ธ๋์์ ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋ ธ๋๋ฅผ ์ฐพ์ ๋ฐฉ๋ฌธ ํ ์คํ์ ์ฝ์
๋ ์ด์ ๋ฐฉ๋ฌธํ ๋ ธ๋๊ฐ ์์ผ๋ฉด ์คํ์์ ๋ ธ๋๋ฅผ ๊บผ๋ด๋ฉฐ ๋ฐฑํธ๋ํน(Backtracking)
๋ชฉํ ๋ ธ๋๋ฅผ ์ฐพ๊ฑฐ๋ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ํ์ํ ๋๊น์ง ๋ฐ๋ณต
์ด๋ฏธ์ง ์ถ์ฒ: ์ํค๋ฐฑ๊ณผ, '๊น์ด ์ฐ์ ํ์'
โ DFS์ ํน์ง
โ ์คํ(Stack) ๋๋ ์ฌ๊ท(Recursion)๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ ๊ฐ๋ฅ
โ ๊น์ ๊ณณ์ ์๋ ๋ชฉํ๋ฅผ ๋นจ๋ฆฌ ์ฐพ์ ์ ์์
โ ๊ฒฝ๋ก๊ฐ ๋งค์ฐ ๊น๊ฑฐ๋ ๋ฌดํ ๋ฃจํ๊ฐ ๋ฐ์ํ ์ ์์ โ ๋ฐฑํธ๋ํน ํ์
โ DFS ์ฝ๋ ๊ตฌํ (Python)
def dfs(graph, node, visited=None):
if visited is None:
visited = set()
visited.add(node)
print(node, end=' ')
for neighbor in graph[node]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
return visited
# ์์ ๊ทธ๋ํ
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
# DFS ํธ์ถ
dfs(graph, 'A')
๐ 3. ๋๋น ์ฐ์ ํ์(BFS: Breadth-First Search)
โ BFS๋?
BFS(๋๋น ์ฐ์ ํ์, Breadth First Search)๋ ๋ชจ๋ ์ด์ ๋
ธ๋๋ฅผ ๋จผ์ ํ์ํ ํ, ๋ค์ ๊น์ด์ ๋
ธ๋๋ฅผ ํ์ํ๋ ๋ฐฉ์์
๋๋ค.
์ฆ, ๊ฐ๊น์ด ๊ณณ๋ถํฐ ์ฐจ๋ก๋๋ก ํ์ํ๋ ๋ฐฉ์์
๋๋ค.
๐ BFS ๋์ ๊ณผ์
์์ ๋ ธ๋๋ฅผ ํ(Queue)์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
ํ์์ ๋ ธ๋๋ฅผ ๊บผ๋ด๊ณ , ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋ ธ๋๋ฅผ ๋ชจ๋ ํ์ ์ฝ์
๋ชฉํ ๋ ธ๋๋ฅผ ์ฐพ๊ฑฐ๋ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ํ์ํ ๋๊น์ง ๋ฐ๋ณต
DFS(๊น์ด์ฐ์ ํ์)๊ณผ์ ๋น๊ต
์ด๋ฏธ์ง ์ถ์ฒ: ์ํค๋ฐฑ๊ณผ, ๋๋น์ฐ์ ํ์
โ BFS์ ํน์ง
โ ์ต๋จ ๊ฒฝ๋ก ํ์์ ์ ๋ฆฌ
โ ํ(Queue)๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ
โ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด DFS๋ณด๋ค ๋ง์
โ BFS ์ฝ๋ ๊ตฌํ (Python)
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
vertex = queue.popleft()
print(vertex, end=' ')
for neighbor in graph[vertex]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
# ์์ ๊ทธ๋ํ
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
# BFS ํธ์ถ
bfs(graph, 'A')
๐ BFS ์คํ ๊ฒฐ๊ณผ ์์
A B C D E F
๐ 4. ๊น์ด ์ ํ ํ์(DLS: Depth-Limited Search)
โ DLS๋?
DLS(๊น์ด ์ ํ ํ์)๋ DFS ๋ฐฉ์๊ณผ ๋์ผํ์ง๋ง, ํ์ํ ์ต๋ ๊น์ด๋ฅผ ์ ํํ์ฌ ๋ฌดํ ๋ฃจํ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐฉ์์
๋๋ค.
์ฆ, ๊น์ด ์ ํ์ ์ค์ ํ์ฌ, ํด๋น ๊น์ด๊น์ง๋ง ํ์์ ์ํํฉ๋๋ค.
๐ DLS ๋์ ๊ณผ์
DFS ๋ฐฉ์์ผ๋ก ํ์์ ์งํํ๋, ํ์ฌ ํ์ ๊น์ด๊ฐ ์ ํ ๊น์ด์ ๋๋ฌํ๋ฉด ํ์์ ์ค๋จ
๋ชฉํ ๋ ธ๋๋ฅผ ์ฐพ๊ฑฐ๋ ํ์์ด ๋๋ ๋๊น์ง ๋ฐ๋ณต
โ DLS์ ํน์ง
โ DFS์ ๋ฌดํ ๋ฃจํ ๋ฌธ์ ํด๊ฒฐ ๊ฐ๋ฅ
โ ๋๋ฌด ๊น์ ๊ฒฝ๋ก๋ฅผ ํ์ํ์ง ์๋๋ก ์กฐ์ ๊ฐ๋ฅ
โ ์ต์ ํด๋ฅผ ๋ณด์ฅํ์ง ์์ผ๋ฉฐ, ๋ชฉํ๊ฐ ๊น์ ๊ณณ์ ์์ผ๋ฉด ํ์ ์คํจ ๊ฐ๋ฅ
โ DLS ์ฝ๋ ๊ตฌํ (Python)
def dls(graph, node, goal, depth_limit, depth=0):
if depth > depth_limit:
return False
print(node, end=' ')
if node == goal:
return True
for neighbor in graph[node]:
if dls(graph, neighbor, goal, depth_limit, depth+1):
return True
return False
# ์์ ๊ทธ๋ํ
graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
}
# DLS ํธ์ถ
print("\nDLS ํ์ ๊ฒฐ๊ณผ:")
dls(graph, 'A', 'F', 2)
๐ DLS ์คํ ๊ฒฐ๊ณผ ์์ (๊น์ด ์ ํ 2์ผ ๋)
A B D E C
๐ 5. ๋ฐ๋ณต์ ๊น์ด ์ฌํ ํ์(IDDFS: Iterative Deepening Depth-First Search)
โ IDDFS๋?
IDDFS(๋ฐ๋ณต์ ๊น์ด ์ฌํ ํ์)๋ ๊น์ด ์ ํ ํ์(DLS)์ ์ฌ๋ฌ ๋ฒ ์ํํ๋ฉด์ ํ์ ๊น์ด๋ฅผ ์ ์ง์ ์ผ๋ก ์ฆ๊ฐ์ํค๋ ๋ฐฉ์์
๋๋ค.
์ฆ, ๊น์ด ์ ํ์ 1๋ถํฐ ์์ํด ์ ์ง์ ์ผ๋ก ๋๋ ค๊ฐ๋ฉด์ ํ์ํ๋ ๋ฐฉ์์ผ๋ก,
DFS์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๊ณผ BFS์ ์ต๋จ ๊ฒฝ๋ก ๋ณด์ฅ ์ฅ์ ์ ๊ฒฐํฉํ ์๊ณ ๋ฆฌ์ฆ์
๋๋ค.
๐ IDDFS ๋์ ๊ณผ์
๊น์ด ์ ํ ํ์(DLS)์ ๊น์ด 0๋ถํฐ ์์ํ์ฌ ํ๋์ฉ ์ฆ๊ฐ์ํค๋ฉฐ ๋ฐ๋ณต ์คํ
๋ชฉํ ๋ ธ๋๋ฅผ ์ฐพ๊ฑฐ๋ ํ์์ด ๋๋ ๋๊น์ง ๋ฐ๋ณต
DLS์ ๊น์ด๋ฅผ ๊ณ์ ์ฆ๊ฐ์ํค๋ฉฐ ์ต์ ์ ํด๋ฅผ ์ฐพ์
โ IDDFS์ ํน์ง
โ DFS์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๊ณผ BFS์ ์ต๋จ ๊ฒฝ๋ก ๋ณด์ฅ ์ฅ์ ์ ๊ฒฐํฉํ ๋ฐฉ์
โ ๋ฉ๋ชจ๋ฆฌ๋ฅผ DFS๋ณด๋ค ์ ๊ฒ ์ฌ์ฉํ๋ฉด์๋ BFS์ฒ๋ผ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ์ ์์
โ ์ค๋ณต ํ์์ด ๋ง์์ง ์ ์์ด ์คํ ์๊ฐ์ด ๊ธธ์ด์ง ์๋ ์์
โ IDDFS ์ฝ๋ ๊ตฌํ (Python)
def dls(graph, node, goal, depth_limit, depth=0):
"""๊น์ด ์ ํ ํ์(DLS) ํจ์"""
if depth > depth_limit:
return False
print(node, end=' ')
if node == goal:
return True
for neighbor in graph[node]:
if dls(graph, neighbor, goal, depth_limit, depth + 1):
return True
return False
def iddfs(graph, start, goal, max_depth):
"""๋ฐ๋ณต์ ๊น์ด ์ฌํ ํ์(IDDFS) ํจ์"""
for depth in range(max_depth + 1):
if dls(graph, start, goal, depth):
return True
return False
# ์์ ๊ทธ๋ํ
graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
}
# IDDFS ํธ์ถ
print("\nIDDFS ํ์ ๊ฒฐ๊ณผ:")
iddfs(graph, 'A', 'F', 3)
๐ IDDFS ์คํ ๊ฒฐ๊ณผ ์์ (์ต๋ ๊น์ด 3์ผ ๋)
A B D E C F
โ IDDFS์ ์ฅ์ ๊ณผ ๋จ์
๐ข ์ฅ์
์ฅ์ ์ค๋ช | |
์ต์ ํด(Shortest Path) ๋ณด์ฅ | BFS์ฒ๋ผ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ์ ์์ |
๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ด ์ ์ | DFS์ฒ๋ผ ๊น์ด ํ์ ๋ฐฉ์์ด๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ |
๋ฌดํ ๋ฃจํ ๋ฐฉ์ง ๊ฐ๋ฅ | ๊น์ด ์ ํ์ด ์ฆ๊ฐํ๋ฉด์ ๊ฒฐ๊ตญ ๋ชจ๋ ๋ ธ๋๋ฅผ ํ์ ๊ฐ๋ฅ |
๐ด ๋จ์
๋จ์ ์ค๋ช | |
์ค๋ณต ํ์ ๋ฐ์ | ๊น์ด๋ฅผ ์ฆ๊ฐ์ํฌ ๋๋ง๋ค ๋์ผํ ๋ ธ๋๋ฅผ ๋ค์ ํ์ |
์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆด ์ ์์ | ๊น์ด๊ฐ ๊น์ด์ง์๋ก ์ฐ์ฐ๋์ด ๋ง์์ง ์ ์์ |
๐ฏ ๋ง๋ฌด๋ฆฌ: ๋งน๋ชฉ์ ํ์ ์๊ณ ๋ฆฌ์ฆ ๋น๊ต
์๊ณ ๋ฆฌ์ฆํ์ ๋ฐฉ์์ต์ ๊ฒฝ๋ก ๋ณด์ฅ ์ฌ๋ถ์ฅ์ ๋จ์ | ||||
DFS | ๊น์ด ์ฐ์ ํ์ | โ | ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ | ๋ฌดํ ๋ฃจํ ๊ฐ๋ฅ |
BFS | ๋๋น ์ฐ์ ํ์ | โ | ์ต๋จ ๊ฒฝ๋ก ๋ณด์ฅ | ๋ฉ๋ชจ๋ฆฌ ์๋ชจ ๋ง์ |
DLS | ๊น์ด ์ ํ ํ์ | โ | ๋ฌดํ ๋ฃจํ ๋ฐฉ์ง | ์ต์ ๊ฒฝ๋ก ์ฐพ๊ธฐ ์ด๋ ค์ |
IDDFS | ๋ฐ๋ณต์ ๊น์ด ์ฌํ ํ์ | โ | BFS์ฒ๋ผ ์ต๋จ ๊ฒฝ๋ก ๋ณด์ฅ | ์ค๋ณต ํ์ ๋ง์ |