Skip to main content

dynamic-programming

Optimization technique that solves complex problems by breaking them into overlapping subproblems, solving each once, and storing results to avoid redundant computation

설치로 이동

소스 정보

저장소
lev-os/agents
최근 소스 활동
2026년 3월 7일 00:14
감지된 SKILL.md 언어
영어
스타
21
포크
2

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
Dynamic Programming
description
Optimization technique that solves complex problems by breaking them into overlapping subproblems, solving each once, and storing results to avoid redundant computation
# Dynamic Programming Algorithm Paradigm ## What It Is An optimization technique that solves complex problems by breaking them into overlapping subproblems, solving each subproblem once, and storing the results to avoid redundant computation. Unlike divide-and-conquer where subproblems are independent, DP exploits the overlap by remembering solutions (memoization or tabulation) to transform exponential-time recursive algorithms into polynomial-time solutions. ## When to Use It - Problem has **overlapping subproblems** (same subproblem solved multiple times) - Problem exhibits **optimal substructure** (optimal solution contains optimal solutions to subproblems) - Recursive solution exists but has exponential time due to repeated computation - Need to find optimal value (min/max) or count all possible solutions - Problem involves sequences, trees, graphs with state-dependent decisions - Trade space for time is acceptable (store intermediate results) ## Execution Steps ### 1. Clarify the State Identify what variables fully describe a subproblem. State should be minimal but complete - enough to uniquely identify each subproblem. Common state patterns: position in array, remaining capacity, substring boundaries, node in graph. **Action**: Ask "What parameters change in the recursion?" Write state as `dp[i]`, `dp[i][j]`, or `dp[state_tuple]`. Example: Fibonacci → `dp[n]`; Knapsack → `dp[item][capacity]`. ### 2. Define the Recurrence (State Transition) Express the solution for state `dp[i]` in terms of smaller/simpler states. This is the heart of DP. Identify the decision at each step and how choices affect the state. **Action**: Write the recurrence relation mathematically. Example: `dp[i] = min(dp[i-1] + cost1, dp[i-2] + cost2)`. Ensure base cases are clearly defined (typically `dp[0]` or boundary conditions). ### 3. Choose Implementation Approach **Top-Down (Memoization)**: Start from the problem, recurse naturally, cache results in a memo table. Easier to write, only computes needed subproblems. **Bottom-Up (Tabulation)**: Start from base cases, iteratively fill table in topological order. More efficient (no recursion overhead), easier to optimize space. **Action**: For interview/rapid prototyping → top-down. For production/performance → bottom-up. Consider space optimization (often reduce from O(n²) to O(n) by keeping only last row). ### 4. Identify the Choices At each state, what decisions can you make? For optimization problems: which option to take? For counting: how many ways to proceed? Choices determine the recurrence structure. **Action**: List all valid transitions from current state. Example: Coin change → try each coin denomination; Longest increasing subsequence → include or skip current element. ### 5. Code the Solution Implement the recurrence with proper base cases. For top-down: add memoization decorator or explicit cache checks. For bottom-up: initialize table, iterate in correct order (ensure dependencies computed first), extract final answer. **Action**: Write base case first, then recursive/iterative logic, finally return `dp[target_state]`. Test with small examples manually before running. ### 6. Analyze and Optimize Calculate time complexity (usually O(num_states × transitions_per_state)) and space complexity. Look for space optimization opportunities: rolling arrays, state compression, dimension reduction. **Action**: Measure runtime on test cases. Profile memory usage. Apply space optimizations if needed (e.g., Fibonacci from O(n) space to O(1)). ## Real-World Applications **Finance & Operations Research** - Portfolio optimization: maximize returns given constraints - Resource allocation: knapsack variants for budget distribution - Inventory management: optimal ordering policies over time **Bioinformatics** - Sequence alignment (Needleman-Wunsch, Smith-Waterman): DNA/protein matching - RNA folding prediction: secondary structure optimization - Phylogenetic tree construction: evolutionary distance minimization **Text Processing** - Edit distance (Levenshtein): spell checkers, DNA matching, diff tools - Longest common subsequence: version control, plagiarism detection - Word break problem: natural language processing, search query parsing **Game Theory & AI** - Optimal game strategy: chess endgames, poker decision trees - Reinforcement learning: value iteration, policy optimization (Bellman equations) - Path planning: robot navigation with state-dependent costs **Computer Graphics & Vision** - Image segmentation: seam carving, optimal path finding - Video encoding: motion estimation, compression optimization - Texture synthesis: dynamic texture generation **Compiler Optimization** - Code generation: register allocation, instruction scheduling - Matrix chain multiplication: optimal parenthesization for expression evaluation - Optimal binary search trees: minimize expected search time ## Anti-Patterns **Using DP when subproblems don't overlap** → Wastes space storing unused results; use divide-and-conquer instead. **Wrong state definition** → Leads to incorrect recurrence or exponential state space; rethink what truly defines a subproblem. **Missing base cases** → Causes infinite recursion or index errors; always handle boundary conditions explicitly. **Computing states in wrong order (bottom-up)** → Accesses uninitialized values; ensure topological order respects dependencies. **Not checking for optimality structure** → DP won't work if optimal solution doesn't contain optimal subsolutions; verify this property first. **Over-engineering the recurrence** → Including unnecessary state dimensions bloats space complexity; keep state minimal. ## Success Metrics - Time complexity reduction from exponential to polynomial (e.g., O(2ⁿ) → O(n²)) - Correctness on all test cases including edge cases (empty input, single element) - Space efficiency (can O(n²) be reduced to O(n)?) - Code clarity (recurrence relation obvious from implementation?) - Performance on large inputs (n=10,000+) vs. recursive baseline ## Related Frameworks - **Divide and Conquer**: For non-overlapping subproblems (convert DP to D&C by removing memoization) - **Greedy Algorithms**: When local optimal choices suffice (DP guarantees global optimum) - **Backtracking**: For constraint satisfaction without optimization - **Memoization Pattern**: General caching technique beyond DP - **Bellman-Ford, Dijkstra**: Graph shortest paths using DP principles ## Common Pitfalls - Forgetting to initialize DP table with sentinel values (infinity for min, zero for max) - Off-by-one errors in state indices (especially for substrings/subarrays) - Not handling negative numbers/weights when problem assumes non-negative - Confusing "optimal substructure" with "subproblem independence" (DP needs former, not latter) - Implementing top-down without memoization (defeating the purpose) - Using recursion with memoization for extremely deep problems (stack overflow) ## Tools & Resources - **Visualization**: Dynamic Programming Visualizer (algorithm-visualizer.org), LeetCode's DP Explorer - **Practice Platforms**: LeetCode (DP tag ~400 problems), Codeforces DP category, Project Euler - **Books**: "Dynamic Programming for Coding Interviews" (Meenakshi), "Algorithms" (Dasgupta, Papadimitriou, Vazirani) - **Pattern Guides**: "Dynamic Programming Patterns" (14 common patterns: Fibonacci, 0/1 Knapsack, Unbounded Knapsack, LCS, LIS, Palindromes, etc.) - **Debugging**: Print DP table after computation to verify values, use small test cases (n≤5) for manual checking ## Classic Problem Patterns **Linear DP**: Fibonacci, climbing stairs, house robber (1D state, O(n)) **Grid DP**: Unique paths, minimum path sum, edit distance (2D state, O(n×m)) **Knapsack Variants**: 0/1 knapsack, unbounded knapsack, subset sum (2D → 1D optimization possible) **Interval DP**: Matrix chain multiplication, palindrome partitioning (O(n³) with 2 endpoints as state) **Tree DP**: House robber III, binary tree cameras (state = node + subtree status) **Bitmask DP**: Traveling salesman, subset enumeration (state = visited set as bitmask) --- *Framework Type*: Algorithm Design Paradigm *Domain*: Computer Science, Optimization *Practitioner Score*: 10/10 - Essential for technical interviews, powers production systems at scale *Complexity*: Medium-High - Requires recurrence relation insight and state design skills *Prerequisites*: Recursion, mathematical induction, basic combinatorics, time/space complexity analysis
GitHub에서 보기