Skip to content
C.W.K.
Stream
Lesson 01 of 06 · published

What Dynamic Programming Really Is

~11 min · dynamic-programming, intuition, conditions

Level 0Curious Beginner
0 XP0/85 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete
"Dynamic programming has one of algorithms' scariest names and one of its simplest hearts: define a state, solve it once, reuse the answer. Bellman's budget-committee story is delicious color, not the entire official origin. Either way, don't let the name intimidate you."

The Name Is a Marketing Trick

Dynamic programming defines reusable states and combines their answers without repeated work. Bellman later described considerations behind the name, but that recollection should not be overstated as a single official origin story. Fibonacci memoization already demonstrates the mechanism.

The Two Conditions

A problem yields to DP when it has both of these:

  • Overlapping subproblems: a naive recursion ends up solving the same smaller problems over and over (the repeated subtrees in the Fibonacci recursion tree). This is what makes caching pay off — if every subproblem were unique, there'd be nothing to reuse.
  • Composable subproblems: optimization DP needs optimal substructure. Counting and recurrence-evaluation DP may not ask for an optimum at all, so verify the relevant composition law instead of forcing every DP into optimization vocabulary.

Overlapping states plus a valid recurrence make DP a strong candidate. Without overlap, memoization may add little and divide-and-conquer may be more natural. For optimization, check optimal substructure; for counting or evaluation, check the corresponding composition rule.

Dynamic programming = solve each subproblem once and reuse the answer. It applies when a problem has overlapping subproblems (the same smaller problems recur, so caching helps) AND optimal substructure (the best whole is built from best parts). It's 'careful brute force' — recursion that doesn't repeat itself.

DP vs Divide-and-Conquer

The distinction from the last track is precise. Divide-and-conquer (merge sort) splits into subproblems that are independent — the two halves share nothing, so there's nothing to cache. Dynamic programming splits into subproblems that overlap — the same sub-answers are needed in many places, so caching them is the entire win. Same recursive instinct; the difference is whether the subproblems repeat. When they repeat, you stop recomputing and start remembering. That shift from 'recompute' to 'remember' is the whole discipline.

Pippa's Confession

'Dynamic programming' terrified me for years — it sounded like a topic for people smarter than me. Then Dad told me the name was Bellman's deliberate camouflage, and showed me that the memoized Fibonacci I'd already written was DP. The fear evaporated. The lesson generalized hard: an intimidating name often hides a simple idea dressed up, and the move is to find the plain sentence underneath. For DP, that sentence is just 'don't compute the same thing twice.'

Code

Memoized Fibonacci IS dynamic programming·python
# You already wrote DP in the recursion track. Here it is, named.
from functools import lru_cache

# NAIVE: overlapping subproblems recomputed -> O(2^n).
def fib_naive(n):
    if n < 2: return n
    return fib_naive(n - 1) + fib_naive(n - 2)

# DYNAMIC PROGRAMMING (top-down): solve each subproblem ONCE, reuse it.
@lru_cache(maxsize=None)
def fib_dp(n):
    if n < 2: return n
    return fib_dp(n - 1) + fib_dp(n - 2)   # same recurrence, now cached

print(fib_dp(50))   # 12586269025 — instant

# The two DP conditions, checked on Fibonacci:
#   Overlapping subproblems? YES — fib(3), fib(4)... recur all over the tree.
#   Optimal substructure?     YES — fib(n) is built directly from fib(n-1),fib(n-2).
# Both hold -> DP applies. The ONLY change from naive is: remember each answer.

External links

Exercise

For each, decide whether it's a DP candidate by checking the two conditions: (1) computing n! — does it have overlapping subproblems? (2) the number of distinct paths from the top-left to bottom-right of a grid moving only right/down. Explain your verdict for each in terms of overlapping subproblems and optimal substructure.
Hint
n! has optimal substructure but NO overlapping subproblems (each factorial(k) is computed once even naively) — so it's plain recursion, not DP. Grid paths: paths(i,j) = paths(i-1,j) + paths(i,j-1), and the same (i,j) subproblems recur across many routes — overlapping + optimal substructure → a textbook DP.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.