[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,93 +2,182 @@
|
||||
id: wiki-2026-0508-dynamic-programming
|
||||
title: Dynamic Programming
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-DYPR-001]
|
||||
aliases: [DP, 동적 계획법, 동적 프로그래밍]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.97
|
||||
tags: [auto-reinforced, dynamic-programming, algorithms, Optimization, memoization, subproblems]
|
||||
confidence_score: 0.95
|
||||
verification_status: applied
|
||||
tags: [algorithms, dp, optimization, memoization, tabulation]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
language: python
|
||||
framework: none
|
||||
---
|
||||
|
||||
# [[Dynamic-Programming|Dynamic-Programming]]
|
||||
# Dynamic Programming
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> "똑똑한 반복의 기술: 복잡한 문제를 작은 부분 문제로 쪼개고, 한 번 구한 정답은 메모리에 기억(Memoization)해두었다가 다시 사용하는 방식으로 중복 연산을 획기적으로 줄이는 알고리즘 최적화의 정수."
|
||||
## 매 한 줄
|
||||
> **"매 overlapping subproblem 의 cache 의 의 의 exponential → polynomial"**. 매 1953 Bellman 의 명명 ("dynamic" 의 RAND 의 selling reason). 매 modern algo 의 universal tool — 매 Bioinformatics, ML training, RL value iteration 의 base.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
동적 계획법(Dynamic-Programming)은 문제를 해결하기 위한 알고리즘 설계 패러다임입니다.
|
||||
## 매 핵심
|
||||
|
||||
1. **두 가지 필수 조건**:
|
||||
* **Overlapping Subproblems**: 똑같은 작은 문제들이 반복해서 나타남.
|
||||
* **Optimal Substructure**: 부분 문제의 최적해를 모으면 전체 문제의 최적해가 됨.
|
||||
2. **구현 방식**:
|
||||
* **Top-Down (Memoization)**: 재귀를 사용하되 계산 결과를 저장.
|
||||
* **Bottom-Up (Tabulation)**: 작은 문제부터 순서대로 표를 채워나감.
|
||||
3. **왜 중요한가?**:
|
||||
* 지수 함수적으로 늘어나는 시간 복잡도([[Brute-force|Brute-force]])를 다항 시간 이내로 줄여주어, 현실적으로 풀 수 없는 문제를 해결 가능하게 만듦. (Optimization과 연결)
|
||||
### 매 두 조건 (DP applicability)
|
||||
1. **Optimal substructure**: 매 optimal solution 의 sub-optimal solution 의 의 build.
|
||||
2. **Overlapping subproblems**: 매 same subproblem 의 repeatedly 의 solve.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌**: 과거에는 알고리즘 테스트용 '수학적 기법 정책'으로만 여겨졌으나, 현대 정책은 강화학습의 핵심인 '가치 함수 업데이트 정책(벨만 업데이트)'의 근간 정책으로 재평가됨(RL Update).
|
||||
- **정책 변화(RL Update)**: 거대 모델의 추론 최적화 정책에서, 토큰 생성 시 반복되는 연산을 캐싱하는 'KV 캐시 정책' 또한 현대적인 동적 계획법의 연장선상에 있는 최적화 정책임.
|
||||
### 매 두 style
|
||||
- **Top-down (memoization)**: recursion + cache. 매 declarative, lazy.
|
||||
- **Bottom-up (tabulation)**: iterative table fill. 매 stack-safe, faster constant.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- [[Brute-force|Brute-force]], [[Optimization|Optimization]], [[Combinatorial-Optimization|Combinatorial-Optimization]], [[Reinforcement Learning (RL)|Reinforcement Learning (RL)]], [[Search-Optimization|Search-Optimization]]
|
||||
- **Modern Tech/Tools**: Fibonacci, Knapsack problem solvers, Bio-informatics sequence [[Alignment|Alignment]].
|
||||
---
|
||||
### 매 state design
|
||||
- **state**: 매 minimal info 의 의 의 subproblem 의 identify.
|
||||
- **transition**: 매 state → state 의 recurrence.
|
||||
- **base case**: 매 smallest 의 known answer.
|
||||
- **answer**: 매 final state 의 retrieve.
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### 매 응용
|
||||
1. Bioinformatics: sequence alignment (Needleman-Wunsch).
|
||||
2. NLP: edit distance, CKY parsing, Viterbi.
|
||||
3. RL: Bellman value iteration.
|
||||
4. Graph: Floyd-Warshall, Bellman-Ford.
|
||||
5. Compiler: register allocation, instruction scheduling.
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
## 💻 패턴
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
### Fibonacci (intro example)
|
||||
```python
|
||||
from functools import lru_cache
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
# Top-down
|
||||
@lru_cache(maxsize=None)
|
||||
def fib(n):
|
||||
if n < 2: return n
|
||||
return fib(n-1) + fib(n-2)
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
# Bottom-up O(1) space
|
||||
def fib_bu(n):
|
||||
if n < 2: return n
|
||||
a, b = 0, 1
|
||||
for _ in range(n - 1):
|
||||
a, b = b, a + b
|
||||
return b
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### 0/1 Knapsack
|
||||
```python
|
||||
def knapsack(weights: list[int], values: list[int], capacity: int) -> int:
|
||||
n = len(weights)
|
||||
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
|
||||
for i in range(1, n + 1):
|
||||
for w in range(capacity + 1):
|
||||
if weights[i-1] <= w:
|
||||
dp[i][w] = max(dp[i-1][w], dp[i-1][w - weights[i-1]] + values[i-1])
|
||||
else:
|
||||
dp[i][w] = dp[i-1][w]
|
||||
return dp[n][capacity]
|
||||
# Time O(n·W), Space O(n·W) — can compress to O(W) with reverse iteration
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Longest Common Subsequence (LCS)
|
||||
```python
|
||||
def lcs(a: str, b: str) -> int:
|
||||
n, m = len(a), len(b)
|
||||
dp = [[0] * (m + 1) for _ in range(n + 1)]
|
||||
for i in range(1, n + 1):
|
||||
for j in range(1, m + 1):
|
||||
if a[i-1] == b[j-1]:
|
||||
dp[i][j] = dp[i-1][j-1] + 1
|
||||
else:
|
||||
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
|
||||
return dp[n][m]
|
||||
```
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Edit Distance (Levenshtein)
|
||||
```python
|
||||
def edit_distance(a: str, b: str) -> int:
|
||||
n, m = len(a), len(b)
|
||||
dp = [[0] * (m + 1) for _ in range(n + 1)]
|
||||
for i in range(n + 1): dp[i][0] = i
|
||||
for j in range(m + 1): dp[0][j] = j
|
||||
for i in range(1, n + 1):
|
||||
for j in range(1, m + 1):
|
||||
if a[i-1] == b[j-1]:
|
||||
dp[i][j] = dp[i-1][j-1]
|
||||
else:
|
||||
dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
|
||||
return dp[n][m]
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Coin Change (min coins)
|
||||
```python
|
||||
def coin_change(coins: list[int], amount: int) -> int:
|
||||
dp = [float('inf')] * (amount + 1)
|
||||
dp[0] = 0
|
||||
for x in range(1, amount + 1):
|
||||
for c in coins:
|
||||
if c <= x:
|
||||
dp[x] = min(dp[x], dp[x - c] + 1)
|
||||
return dp[amount] if dp[amount] != float('inf') else -1
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### Bitmask DP (TSP)
|
||||
```python
|
||||
def tsp(dist: list[list[int]]) -> int:
|
||||
n = len(dist)
|
||||
INF = float('inf')
|
||||
dp = [[INF] * n for _ in range(1 << n)]
|
||||
dp[1][0] = 0 # start at 0 with mask {0}
|
||||
for mask in range(1, 1 << n):
|
||||
for u in range(n):
|
||||
if not (mask & (1 << u)) or dp[mask][u] == INF: continue
|
||||
for v in range(n):
|
||||
if mask & (1 << v): continue
|
||||
new_mask = mask | (1 << v)
|
||||
dp[new_mask][v] = min(dp[new_mask][v], dp[mask][u] + dist[u][v])
|
||||
return min(dp[(1 << n) - 1][u] + dist[u][0] for u in range(1, n))
|
||||
# O(n²·2ⁿ) — feasible for n ≤ 20
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| 매 overlapping subproblem 의 detect | DP |
|
||||
| 매 unique subproblem (no overlap) | divide & conquer |
|
||||
| 매 greedy 의 optimal proof 가능 | greedy (faster, less memory) |
|
||||
| 매 state 의 huge | approximate DP / RL |
|
||||
| 매 small recursion depth | top-down (cleaner) |
|
||||
| 매 deep recursion 의 우려 | bottom-up |
|
||||
| 매 memory 의 tight | rolling array (O(prev) 의 의) |
|
||||
|
||||
**기본값**: 매 first attempt 의 top-down + memo. 매 deep / huge 의 의 의 bottom-up.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Algorithm Design]] · [[Optimization]]
|
||||
- 변형: [[Memoization]] · [[Tabulation]] · [[Bitmask DP]] · [[Tree DP]] · [[Digit DP]]
|
||||
- 응용: [[Knapsack Problem]] · [[LCS]] · [[Edit Distance]] · [[Bellman-Ford]] · [[Floyd-Warshall]] · [[Viterbi Algorithm]]
|
||||
- Adjacent: [[Greedy Algorithms]] · [[Divide and Conquer]] · [[Branch and Bound]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 optimization problem 의 overlapping subproblem 의 detect, 매 string/sequence problem, 매 counting problem (combinatorial), 매 RL value function 의 의.
|
||||
**언제 X**: 매 unique subproblem (D&C 의 의), 매 greedy 의 proven optimal, 매 huge state space 의 approximation 의 의 (NN, MCTS).
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **state 의 over-include**: 매 unnecessary dim 의 의 의 의 exponential blow-up.
|
||||
- **base case X**: 매 infinite recursion / wrong result.
|
||||
- **mutable default args** (Python): `def f(x, memo={})` 의 cross-call leak.
|
||||
- **bottom-up 의 wrong order**: 매 state 의 dependency 의 의 의 의 의 fill 의 X.
|
||||
- **`@lru_cache` with mutable args**: list / dict 의 의 의 hash error — tuple 의 의.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Bellman 1957 "Dynamic Programming"; CLRS Ch 15; Kleinberg-Tardos Ch 6).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — DP foundations with knapsack, LCS, edit distance, bitmask TSP |
|
||||
|
||||
Reference in New Issue
Block a user