Skip to content
Skills Library
Programming · Learning & explanation

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)

Licence
MIT
Last repository change
09.06.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
12
Scripts
0
HTML comments
0
URLs in SKILL.md
2
Deprecation

No signals detected. Repository changed on 09.06.2026, without references to retired models or APIs.

Licence

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

  1. Overview
  2. Core Principles
  3. Two Approaches
  4. The DP Framework
  5. Classic Problems
  6. DP Problem Complexity Summary
  7. Memoization vs Tabulation: When to Use Which
  8. Recognizing DP Problems
  9. Best Practices
Original SKILL.md headings · 221 lines, 1,452 words
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

RepositoryScoreLicence
This page · Tyler-R-Kendrick/agent-skills100MIT
SPIRAL-EDWIN/MCM-ICM-2601000100MIT
hajibabaie/combinatorial-optimization-skills95MIT

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.…

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.