[κ·Έλν νμ] κΉμ΄ μ°μ νμ(Depth First Search, DFS)
κΉμ΄ μ°μ νμ(Depth-First Search, DFS)
κΉμ΄ μ°μ νμ(DFS)μ κ·Έλν νμ μκ³ λ¦¬μ¦ μ€ νλλ‘, ν μ μ μμ μμνμ¬ κ°λ₯ν κΉμ΄κΉμ§ νμν ν, λ μ΄μ κ° κ³³μ΄ μμΌλ©΄ λλμμ€λ λ°©μ(λ°±νΈλνΉ)μΌλ‘ λμν©λλ€.
πΉ DFS κ°λ
DFSλ μ€ν(μ¬κ· νΈμΆ or λͺ μμ μ€ν)μ μ¬μ©νμ¬ κ·Έλνλ₯Ό κΉκ² νμνλ λ°©λ²μ λλ€.
- λ¨Όμ νμ¬ λ Έλλ₯Ό λ°©λ¬Ένκ³ ,
- λ°©λ¬Ένμ§ μμ μΈμ λ Έλκ° μμΌλ©΄ ν΄λΉ λ Έλλ‘ μ΄λνμ¬ νμμ κ³μν¨.
- λ μ΄μ λ°©λ¬Έν λ Έλκ° μμΌλ©΄ μ΄μ λ Έλ(λΆλͺ¨ λ Έλ)λ‘ λμκ°(λ°±νΈλνΉ).
πΉ DFS λμ λ°©μ
DFSμ κΈ°λ³Έ λμ μμλ λ€μκ³Ό κ°μ΅λλ€.
- μμ λ Έλλ₯Ό λ°©λ¬Ένκ³ λ°©λ¬Έ μ²λ¦¬
- νμ¬ λ
Έλμμ κ° μ μλ λ
Έλλ₯Ό νμΈ
- λ°©λ¬Ένμ§ μμ λ Έλκ° μμΌλ©΄ ν΄λΉ λ Έλλ‘ μ΄λ
- λ°©λ¬Έν λ ΈλλΌλ©΄ μ€ν΅
- λ μ΄μ λ°©λ¬Έν λ Έλκ° μμΌλ©΄ μ΄μ λ Έλλ‘ λλμκ°
- λͺ¨λ λ Έλλ₯Ό λ°©λ¬Έν λκΉμ§ 2~3 κ³Όμ λ°λ³΅
πΉ DFS ꡬν λ°©λ²
DFSλ λ κ°μ§ λ°©μμΌλ‘ ꡬνν μ μμ΅λλ€.
- μ¬κ·(Recursive) λ°©μ
- μ€ν(Stack) μ¬μ© λ°©μ(λ°λ³΅λ¬Έ)
π’ 1. DFS μ¬κ·(Recursive) λ°©μ ꡬν (Python)
def dfs_recursive(graph, node, visited):
if node in visited: # μ΄λ―Έ λ°©λ¬Έν κ²½μ° μ’
λ£
return
visited.add(node) # λ°©λ¬Έ μ²λ¦¬
print(node, end=" ") # λ°©λ¬Έν λ
Έλ μΆλ ₯
for neighbor in graph[node]: # μΈμ λ
Έλ νμ
dfs_recursive(graph, neighbor, visited)
# κ·Έλν (μΈμ 리μ€νΈ λ°©μ)
graph = {
1: [2, 3],
2: [4, 5],
3: [6, 7],
4: [],
5: [],
6: [],
7: []
}
visited_set = set()
dfs_recursive(graph, 1, visited_set)
μΆλ ₯:
1 2 4 5 3 6 7
π μ¬κ· λ°©μμ μ€νμ μ΄μ©ν κ²κ³Ό λμΌν μλ¦¬λ‘ λμν©λλ€.
π’ 2. DFS μ€ν(Stack) μ¬μ© λ°©μ ꡬν (λ°λ³΅λ¬Έ)
def dfs_stack(graph, start):
visited = set()
stack = [start] # μ€ν μ΄κΈ°ν
while stack:
node = stack.pop() # μ€νμμ λ
Έλ κΊΌλ΄κΈ°
if node not in visited:
visited.add(node) # λ°©λ¬Έ μ²λ¦¬
print(node, end=" ")
# μ€νμ μΈμ λ
Έλλ₯Ό μΆκ° (λ°λλ‘ λ£μΌλ©΄ μμ μ μ§)
stack.extend(reversed(graph[node]))
# κ·Έλν (μΈμ 리μ€νΈ λ°©μ)
graph = {
1: [2, 3],
2: [4, 5],
3: [6, 7],
4: [],
5: [],
6: [],
7: []
}
dfs_stack(graph, 1)
μΆλ ₯:
1 2 4 5 3 6 7
π μ€νμ μ¬μ©νλ©΄ μ¬κ· μμ΄ DFSλ₯Ό ꡬνν μ μμ΅λλ€.
πΉ DFS vs BFS μ°¨μ΄μ
λΉκ΅ νλͺ© | DFS(Depth-First Search) | BFS(Breadth-First Search) |
νμ λ°©μ | μ΅λν κΉμ΄ νμ ν λ°±νΈλνΉ | νμ¬ λ 벨(λλΉ)μμ νμ ν λ€μ λ λ²¨λ‘ μ΄λ |
μλ£κ΅¬μ‘° | μ€ν (or μ¬κ· νΈμΆ) | ν (Queue) |
κ²½λ‘ νμ | λͺ¨λ κ²½λ‘λ₯Ό νμν΄μΌ νλ κ²½μ° μ ν© | μ΅λ¨ κ²½λ‘(κ°μ€μΉ μλ κ·Έλν) νμμ μ ν© |
ꡬν λμ΄λ | λΉκ΅μ κ°λ¨ | μλμ μΌλ‘ λ³΅μ‘ |
μ¬μ© μμ | λ°±νΈλνΉ(λ―Έλ‘ μ°ΎκΈ°, νΌμ¦ ν΄κ²°, μ‘°ν©) | μ΅λ¨ κ²½λ‘ νμ (κΈΈ μ°ΎκΈ°, λ€νΈμν¬ νμ) |
πΉ DFS μμ© μ¬λ‘
- κ·Έλν νμ
- μ°κ²° μμ μ°ΎκΈ°, κ²½λ‘ νμ
- λ°±νΈλνΉ λ¬Έμ ν΄κ²°
- νΌμ¦ λ¬Έμ (μ: N-Queen λ¬Έμ )
- μ‘°ν©(combination)κ³Ό μμ΄(permutation)
- λ€νΈμν¬ μ°κ²° μ¬λΆ νμΈ
- λ€νΈμν¬ κ·Έλνμμ μ°κ²° μ¬λΆ κ²μ¬
- μ¬μ΄ν΄ κ²μΆ
- λ°©ν₯/무방ν₯ κ·Έλνμμ μ¬μ΄ν΄ μ‘΄μ¬ μ¬λΆ νμΈ
- λ―Έλ‘ μ°ΎκΈ° (DFS κΈ°λ° λ°±νΈλνΉ)
- ν κ²½λ‘λ₯Ό λκΉμ§ νμν ν λ€λ₯Έ κ²½λ‘ νμ
- ν κ²½λ‘λ₯Ό λκΉμ§ νμν ν λ€λ₯Έ κ²½λ‘ νμ
πΉ DFS μκ° λ³΅μ‘λ & κ³΅κ° λ³΅μ‘λ
- μκ° λ³΅μ‘λ:
- μΈμ 리μ€νΈ: O(V + E) (μ μ V, κ°μ E)
- μΈμ νλ ¬: O(V²)
- κ³΅κ° λ³΅μ‘λ:
- O(V) (λ°©λ¬Έ μ²λ¦¬ λ°°μ΄, μ€ν/μ¬κ· νΈμΆ μ€ν)
πΉ μ½λ© ν
μ€νΈ λ¬Έμ (λ°±μ€ 2023)
1. λ¬Έμ μ€λͺ
μλΉμ΄κ° μΈμμμ κ°μ₯ μ’μνλ κ²μ μμμ΄κ³ , μ·¨λ―Έλ μμλ₯Ό κ°μ§κ³ λ
Έλ κ²μ΄λ€. μμ¦ μλΉμ΄κ° κ°μ₯ κ΄μ¬μμ΄ νλ μμλ 7331μ΄λ€. 7331μ μμμΈλ°, μ κΈ°νκ²λ 733λ μμμ΄κ³ , 73λ μμμ΄κ³ , 7λ μμμ΄λ€. μ¦, μΌμͺ½λΆν° 1μ리, 2μ리, 3μ리, 4μ리 μ λͺ¨λ μμμ΄λ€! μλΉμ΄λ μ΄λ° μ«μλ₯Ό μ κΈ°ν μμλΌκ³ μ΄λ¦ λΆμλ€.
μλΉμ΄λ Nμ리μ μ«μ μ€μμ μ΄λ€ μλ€μ΄ μ κΈ°ν μμμΈμ§ κΆκΈν΄μ‘λ€. Nμ΄ μ£Όμ΄μ‘μ λ, μλΉμ΄λ₯Ό μν΄ Nμ리 μ κΈ°ν μμλ₯Ό λͺ¨λ μ°Ύμ보μ.(https://www.acmicpc.net/problem/2023)
(μ ν μκ° 2μ΄, 1<= N <= 8)
2. μ²μμ μ¬μ©ν λ°©λ²(C++ 17)
μ²μμλ DFSλ¬Έμ λΌλ κ²μ κΉ¨λ«μ§ λͺ»νκ³ , std::stringμ νμ©ν΄μ λ¬Έμ λ₯Ό νμμ΅λλ€. μ΄κΈ° λ²μ μ μ νμκ°μ νμ© λκ²ΌμΌλ, 2μ λ°°μλ μμκ° λ μ μλ€(2 μ μΈ) λΌλ κ·μΉμ κΉ¨λ«κ³ μ§μλ₯Ό μ μΈνμ 1850ms λ‘ κ²¨μ° ν΅κ³Όνμ΅λλ€. νμ§λ§ Nμ΄ μ‘°κΈμ΄λΌλ λμμ κ²½μ°μλ 볡μ¬μ°μ°κ³Ό λλΆμ΄ μκ°μ΄ λ§μ΄ μμλλ μ’μ§ μμ μ½λμμ΅λλ€. μ°μ λ¨Όμ μ½λλ₯Ό 보μ¬λλ¦¬κ² μ΅λλ€.
// λ°±μ€ 2023
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
bool isPrime(int num) {
if (num <= 1) return false; // 1 μ΄νμ μ«μλ μμκ° μλ
if (num <= 3) return true; // 2μ 3μ μμ
if (num % 2 == 0 || num % 3 == 0) return false; // 2μ 3μΌλ‘ λλμ΄ λ¨μ΄μ§λ©΄ μμκ° μλ
for (int i = 5; i * i <= num; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) return false;
}
return true;
}
int main()
{
int N;
cin >> N;
int min = pow(10, N-1);
int max = pow(10, N);
for (int i = min; i < max; i++)
{
if (i > 10 && i % 2 == 0)
continue;
bool isPrimeNumber = true;
string str = to_string(i);
for (int j = 0; j < str.length(); j++)
{
string strNum;
int idx = 0;
while (idx <= j)
strNum += str[idx++];
int target = stoi(strNum);
if (!isPrime(target))
{
isPrimeNumber = false;
break;
}
}
if (isPrimeNumber)
cout << i << endl;
}
}
3. DFSλ₯Ό νμ©ν μ΅μ’ λ°©λ²(C++ 17)
ν무νκ²λ DFSλ 0msκ° κ±Έλ Έμ΅λλ€. μΌμ μ리μμ μμλ 2, 3, 5, 7 λΏμ΄κ³ κ·Έ μ΄νμ μ¬ μ μλ μλ 5κ°(νμ) λΏμ λλ€. 2 -> 23, 23-> 233 -> 2337 μ²λΌ κΉμ΄ μ°μ λ°©μμΌλ‘ μμΉν΄λκ°λ DFSλ₯Ό νμ©νλ©΄ μ½κ² ν μ μλ€λ κ²μ μ μ μμ΅λλ€. λ¬Έμ λ₯Ό λ³΄κ³ DFSλ₯Ό νμ©ν΄μΌκ² λ€κ³ μκ°νλ κ²μ΄ κ°μ₯ μ€μνλ€κ³ λ³Ό μ μμ΅λλ€.
// λ°±μ€ 2023
#include <iostream>
#include <vector>
using namespace std;
int N;
bool isPrime(int num) {
if (num <= 1) return false; // 1 μ΄νμ μ«μλ μμκ° μλ
if (num <= 3) return true; // 2μ 3μ μμ
if (num % 2 == 0 || num % 3 == 0) return false; // 2μ 3μΌλ‘ λλμ΄ λ¨μ΄μ§λ©΄ μμκ° μλ
for (int i = 5; i * i <= num; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) return false;
}
return true;
}
void DFS(int num, int digit)
{
if (digit == N)
{
if (isPrime(num))
{
cout << num << endl;
return;
}
}
for (int i = 1; i < 10; i += 2)
{
int next = num * 10 + i;
if (isPrime(next))
DFS(next, digit + 1);
}
}
int main()
{
cin >> N;
DFS(2, 1);
DFS(3, 1);
DFS(5, 1);
DFS(7, 1);
}
πΉ μ 리
- DFSλ μ€ν(LIFO) ꡬ쑰λ₯Ό νμ©νμ¬ κ·Έλνλ₯Ό κΉμ΄ νμνλ μκ³ λ¦¬μ¦
- μ¬κ·(Recursive) λ°©μκ³Ό μ€ν(Stack) λ°©μμΌλ‘ ꡬν κ°λ₯
- λ°±νΈλνΉ, λ―Έλ‘ νμ, κ²½λ‘ νμ λ± λ€μν λ¬Έμ ν΄κ²°μ μ¬μ©
- BFSμ λΉκ΅νλ©΄ μ΅λ¨ κ²½λ‘ νμ보λ€λ λͺ¨λ κ²½μ°μ μλ₯Ό νμν λ μ 리ν¨
DFSκ° νμν μν©μ΄λΌλ©΄, μ¬κ· λ°©μκ³Ό μ€ν λ°©μ μ€ μ μ ν λ°©λ²μ μ νν΄μ μ¬μ©νλ©΄ λ©λλ€. π