dynamic-programming
/dynamic-programming
Use when solving optimization problems with overlapping subproblems and optimal substructure. Covers memoization (top-down) vs tabulation (bottom-up), classic DP problems (Knapsack, LCS, LIS, Edit Distance, Coin Change, Matrix Chain, Rod Cutting), and the DP framework. Based on Knuth's TAOCP. USE FOR: optimization problems with overlapping subproblems, memoization strategies, tabulation approaches, recognizing DP problem patterns, state definition and recurrence formulation DO NOT USE FOR: graph shortest paths (use graph-algorithms), sorting (use sorting-searching)
- Author
- Tyler-R-Kendrick ↗
- Repository
- agent-skills ↗
- Licence
- MIT
- Last repository change
- 09.06.2026
Assessment and security
- Files in this package
- 12
- Scripts
- 0
- HTML comments
- 0
- URLs in SKILL.md
- 2
No signals detected. Repository changed on 09.06.2026, without references to retired models or APIs.
MIT, open: use and modify while retaining author attribution.
What it does and when to use it
Use when solving optimization problems with overlapping subproblems and optimal substructure. Covers memoization (top-down) vs tabulation (bottom-up), classic DP problems (Knapsack, LCS, LIS, Edit Distance, Coin Change, Matrix Chain, Rod Cutting), and the DP framework. Based on Knuth's TAOCP. USE FOR: optimization problems with overlapping subproblems, memoization strategies, tabulation approaches, recognizing DP problem patterns, state definition and recurrence formulation DO NOT USE FOR: graph shortest paths (use graph-algorithms), sorting (use sorting-searching)
Original author description
Use when solving optimization problems with overlapping subproblems and optimal substructure. Covers memoization (top-down) vs tabulation (bottom-up), classic DP problems (Knapsack, LCS, LIS, Edit Distance, Coin Change, Matrix Chain, Rod Cutting), and the DP framework. Based on Knuth's TAOCP. USE FOR: optimization problems with overlapping subproblems, memoization strategies, tabulation approaches, recognizing DP problem patterns, state definition and recurrence formulation DO NOT USE FOR: graph shortest paths (use graph-algorithms), sorting (use sorting-searching)
How it works
- Overview
- Core Principles
- Two Approaches
- The DP Framework
- Classic Problems
- DP Problem Complexity Summary
- Memoization vs Tabulation: When to Use Which
- Recognizing DP Problems
- Best Practices
SKILL.md preview
---
name: dynamic-programming
description: |
Use when solving optimization problems with overlapping subproblems and optimal substructure. Covers memoization (top-down) vs tabulation (bottom-up), classic DP problems (Knapsack, LCS, LIS, Edit Distance, Coin Change, Matrix Chain, Rod Cutting), and the DP framework. Based on Knuth's TAOCP.
USE FOR: optimization problems with overlapping subproblems, memoization strategies, tabulation approaches, recognizing DP problem patterns, state definition and recurrence formulation
DO NOT USE FOR: graph shortest paths (use graph-algorithms), sorting (use sorting-searching)
license: MIT
metadata:
displayName: "Dynamic Programming"
author: "Tyler-R-Kendrick"
compatibility: claude, copilot, cursor
references:
- title: "The Art of Computer Programming — Donald Knuth"
url: "https://www-cs-faculty.stanford.edu/~knuth/taocp.html"
- title: "Dynamic Programming — Wikipedia"
url: "https://en.wikipedia.org/wiki/Dynamic_programming"
---
# Dynamic Programming
## Overview
Dynamic programming (DP) is a method for solving problems by breaking them into overlapping subproblems, solving each subproblem once, and storing the results to avoid redundant computation. Knuth discusses dynamic programming techniques throughout *The Art of Computer Programming*, particularly in the context of optimization, sequence analysis, and combinatorial problems. The term was coined by Richard Bellman in the 1950s.
## Core Principles
### Optimal Substructure
A problem exhibits optimal substructure if an optimal solution to the problem contains optimal solutions to its subproblems. This property allows us to build the global optimum from local optima.
**Example**: The shortest path from A to C through B consists of the shortest path from A to B plus the shortest path from B to C.
### Overlapping Subproblems
A problem has overlapping subproblems when the same subproblems are solved repeatedly in a naive recursive approach. DP eliminates this redundancy by storing results.
**Example**: Computing Fibonacci(n) recursively recomputes Fibonacci(k) for each k < n exponentially many times.
## Two Approaches
### Memoization (Top-Down)
Start with the original problem, recurse into subproblems, and cache results as they are computed.
```
FIB_MEMO(n, cache):
if n <= 1: return n
if n in cache: return cache[n]
cache[n] = FIB_MEMO(n - 1, cache) + FIB_MEMO(n - 2, cache)
return cache[n]
```
**Advantages**: Natural to write (follows recursive structure), computes only the subproblems actually needed.
**Disadvantages**: Recursion overhead, potential stack overflow for deep recursion.
### Tabulation (Bottom-Up)
Build a table from the smallest subproblems up to the desired result, iterating in a careful order.
```
FIB_TABLE(n):
if n <= 1: return n
dp[0] = 0, dp[1] = 1
for i = 2 to n:
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
```
**Advantages**: No recursion overhead, easier to optimize space (often only need the last few entries).
**Disadvantages**: May compute subproblems that are never needed, ordering can be less intuitive.
## The DP Framework
When facing a potential DP problem, follow these steps:
### 1. Define the State
Identify what information is needed to describe a subproblem. This becomes the index/key for your DP table.
**Example** (Knapsack): `dp[i][w]` = maximum value using items 1..i with capacity w.
### 2. Write the Recurrence
Express the solution to a subproblem in terms of smaller subproblems.
**Example** (Knapsack):
```
dp[i][w] = max(
dp[i-1][w], // skip item i
dp[i-1][w - weight[i]] + value[i] // take item i (if weight[i] <= w)
)
```
### 3. Identify the Base Case
Define the values for the smallest subproblems that cannot be decomposed further.
**Example** (Knapsack): `dp[0][w] = 0` for all w (no items means no value).
### 4. Determine the Build Order
For tabulation, compute subproblems in an order such that all dependencies are resolved before they are needed.
**Example** (Knapsack): Process items from i = 1 to n, capacities from w = 0 to W.
### 5. Extract the Answer
The answer to the original problem is at a specific location in the DP table.
**Example** (Knapsack): `dp[n][W]`.
### 6. (Optional) Optimize Space
If the recurrence only depends on the previous row or a fixed number of prior entries, reduce the table accordingly.
**Example** (Fibonacci): Only need dp[i-1] and dp[i-2], so use two variables instead of an array.
## Classic Problems
### Fibonacci Sequence
| Approach | Time | Space |
|----------|------|-------|
| Naive recursion | O(2^n) | O(n) stack |
| Memoization | O(n) | O(n) |
| Tabulation | O(n) | O(n) or O(1) optimized |
### 0/1 Knapsack
Given n items with weights and values, and a knapsack of capacity W, maximize the total value without exceeding the capacity. Each item can be taken at most once.
- **State**: `dp[i][w]` = max value using first i items with capacity w
- **Recurrence**: `dp[i][w] = max(dp[i-1][w], dp[i-1][w-wt[i]] + val[i])`
- **Time**: O(n * W)
- **Space**: O(n * W), or O(W) with rolling array
### Unbounded Knapsack
Same as 0/1 Knapsack, but each item can be taken unlimited times.
- **State**: `dp[w]` = max value with capacity w
- **Recurrence**: `dp[w] = max(dp[w], dp[w-wt[i]] + val[i])` for each item i
- **Time**: O(n * W)
- **Space**: O(W)
### Longest Common Subsequence (LCS)
Find the longest subsequence common to two sequences.
- **State**: `dp[i][j]` = length of LCS of first i characters of X and first j characters of Y
- **Recurrence**:
```
if X[i] == Y[j]: dp[i][j] = dp[i-1][j-1] + 1
else: dp[i][j] = max(dp[i-1][j], dp[i][j-1])
```
- **Time**: O(m * n)
- **Space**: O(m * n), or O(min(m, n)) optimized
### Longest Increasing Subsequence (LIS)
Find the length of the longest strictly increasing subsequence.
- **State**: `dp[i]` = length of LIS ending at index i
- **Recurrence**: `dp[i] = max(dp[j] + 1)` for all j < i where A[j] < A[i]
- **Time**: O(n^2), or O(n log n) with patience sorting (binary search on tails)
- **Space**: O(n)
### Edit Distance (Levenshtein Distance)
Minimum number of operations (insert, delete, replace) to transform one string into another.
- **State**: `dp[i][j]` = edit distance between first i characters of X and first j characters of Y
- **Recurrence**:
```
if X[i] == Y[j]: dp[i][j] = dp[i-1][j-1]
else: dp[i][j] = 1 + min(dp[i-1][j], // delete
dp[i][j-1], // insert
dp[i-1][j-1]) // replace
```
- **Time**: O(m * n)
- **Space**: O(m * n), or O(min(m, n)) optimized
### Coin Change
Given coin denominations and a target amount, find the minimum number of coins needed (or the number of ways to make change).
**Minimum coins:**
- **State**: `dp[a]` = minimum coins to make amount a
- **Recurrence**: `dp[a] = min(dp[a - coin] + 1)` for each coin denomination
- **Base case**: `dp[0] = 0`
- **Time**: O(amount * number_of_coins)
- **Space**: O(amount)
### Matrix Chain Multiplication
Find the optimal way to parenthesize a sequence of matrices to minimize total scalar multiplications.
- **State**: `dp[i][j]` = minimum cost to multiply matrices i through j
- **Recurrence**: `dp[i][j] = min(dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j])` for i <= k < j
- **Base case**: `dp[i][i] = 0`
- **Time**: O(n^3)
- **Space**: O(n^2)
### Rod Cutting
Given a rod of length n and prices for each length, find the maximum revenue from cutting the rod.
- **State**: `dp[l]` = maximum revenue for rod of length l
- **Recurrence**: `dp[l] = max(price[k] + dp[l - k])` for 1 <= k <= l
- **Base case**: `dp[0] = 0`
- **Time**: O(n^2)
- **Space**: O(n)
## DP Problem Complexity Summary
| Problem | Time | Space |
|---------|------|-------|
| Fibonacci | O(n) | O(1) optimized |
| 0/1 Knapsack | O(n * W) | O(W) optimized |
| Unbounded Knapsack | O(n * W) | O(W) |
| LCS | O(m * n) | O(min(m, n)) optimized |
| LIS | O(n log n) | O(n) |
| Edit Distance | O(m * n) | O(min(m, n)) optimized |
| Coin Change | O(amount * coins) | O(amount) |
| Matrix Chain Mult. | O(n^3) | O(n^2) |
| Rod Cutting | O(n^2) | O(n) |
## Memoization vs Tabulation: When to Use Which
| Factor | Memoization (Top-Down) | Tabulation (Bottom-Up) |
|--------|----------------------|----------------------|
| Implementation style | Recursive + cache | Iterative + table |
| Subproblem computation | Only those needed | All subproblems |
| Stack overflow risk | Yes (deep recursion) | No |
| Space optimization | Harder | Easier (rolling arrays) |
| Code clarity | Often more intuitive | Requires careful ordering |
| Performance | Function call overhead | Usually faster in practice |
**Guideline**: Start with memoization for clarity and correctness, then convert to tabulation if performance or space optimization is needed.
## Recognizing DP Problems
A problem is likely solvable with DP if:
1. It asks for an **optimal value** (min, max, count) or the **number of ways** to achieve something.
2. It has **overlapping subproblems** -- naive recursion recomputes the same states.
3. It has **optimal substructure** -- the optimal solution builds on optimal sub-solutions.
4. The problem can be parameterized by a **small set of variables** (the state space is manageable).
## Best Practices
- Always verify optimal substructure before applying DP -- not all optimization problems have it (greedy or exhaustive search may be required instead).
- Define your state precisely and minimally -- extra state dimensions explode the table size.
- Validate your recurrence with small examples before coding.
- Consider whether the problem admits a greedy solution (simpler) before committing to DP.
- For interview/competition settings, practice identifying the state and recurrence quickly -- the implementation follows mechanically.
- Reference Knuth's TAOCP for mathematical rigor on sequence problems, optimal search trees, and combinatorial optimization where DP techniques apply.
Files in this package (12)
- AGENTS.md 9 KB
- README.md 1 KB
- SKILL.md 10 KB
- metadata.json 1 KB
- rules/_sections.md 2 KB
- rules/_template.md 1 KB
- rules/dynamic-programming-always-verify-optimal-substructure-before-applying-dp.md 1 KB
- rules/dynamic-programming-consider-whether-the-problem-admits-a-greedy-solution.md 1 KB
- rules/dynamic-programming-define-your-state-precisely-and-minimally-extra-state.md 1 KB
- rules/dynamic-programming-for-interview-competition-settings-practice-identifying.md 1 KB
- rules/dynamic-programming-reference-knuth-s-taocp-for-mathematical-rigor-on-sequence.md 1 KB
- rules/dynamic-programming-validate-your-recurrence-with-small-examples-before-coding.md 1 KB
Versions
| Repository | Score | Licence |
|---|---|---|
| This page · Tyler-R-Kendrick/agent-skills | 100 | MIT |
| SPIRAL-EDWIN/MCM-ICM-2601000 | 100 | MIT |
| hajibabaie/combinatorial-optimization-skills | 95 | MIT |
Database snapshot: 13.11.2026 · package version 983530aa451d (SHA-256 digest of the entire package)
Downloads in the last 30 days: 0 · ranking
Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.
Similar skills
- 100dynamic-programming-interviewer
A mid-to-senior level software engineering interviewer specializing in dynamic programming. Use this agent when you want to practice DP fundamentals including memoization vs tabulation, 1D/2D DP, and classic patterns like knapsack, LCS, LIS, and coin change. It teaches the… - 100dsa-dynamic-programming-1d-memoization-tabulation
Use this skill when solving optimization, counting, and decision problems by breaking them into overlapping 1D sub-problems. - 80role-algorithms:dynamic-programming
Solves optimization problems using dynamic programming — top-down memoization, bottom-up tabulation, state space design, dimension reduction, bitmask DP, interval DP, tree DP (with rerooting), DP on DAGs, and convex hull trick / divide-and-conquer optimizations. Use when solving… - 100dsa-dynamic-programming-2d-knapsack-lcs
Use this skill when solving 2D grid traversals, 0/1 knapsack, edit distance, and longest common subsequence problems. - 100combinatorial
Use when solving problems involving permutations, combinations, backtracking, branch and bound, subset generation, and constraint satisfaction. Covers N-Queens, Sudoku solving, generating functions, and pruning strategies. Based on Knuth's TAOCP Vol. 4A. USE FOR: permutation and… - 100graph-algorithms
Use when working with graph problems including traversal, shortest paths, minimum spanning trees, topological sorting, and connectivity analysis. Covers BFS, DFS, Dijkstra, Bellman-Ford, Floyd-Warshall, Prim, Kruskal, Tarjan, Kosaraju, A*, and Union-Find. Based on Knuth's TAOCP.…