"The mechanics of DP are easy — cache a recurrence. The real skill is two things: noticing 'this is a DP' in the first place, and nailing down what the state should be. Master those and DP stops being scary."
The Recognition Signals
Certain problem phrasings should make 'dynamic programming' light up in your head:
- 'Count the number of ways' to do something (paths through a grid, ways to decode a string, ways to make change).
- 'Minimize / maximize' over a sequence of choices (fewest coins, max loot, longest subsequence, lowest cost path).
- 'Can you partition / select / arrange' to satisfy a constraint (subset sum, knapsack).
- A natural recursion exists, but it recomputes the same subproblems (overlapping) — the loudest signal of all.
- Greedy is tempting but gives wrong answers — like coin change, where 'take the biggest coin' fails. When greed breaks, DP is often the fix.
The Five-Step Framework
Once you suspect DP, design it in five steps — and the first is the one that matters:
- Define the state. Finish the sentence 'dp[...] = the answer to ___.' This is the hard step; get it right and the rest is mechanical, get it wrong and nothing works.
- Write the transition. Express dp[state] in terms of smaller states — the recurrence.
- Identify base cases. The smallest states you can answer directly.
- Choose the order. Top-down (memoize the recursion) or bottom-up (tabulate). Either works.
- Optimize space if needed (keep only the cells still referenced).
Steps 2–5 are routine once step 1 is solid. The entire difficulty of DP concentrates in defining the state — which is why 'write the sentence for dp first' has been the through-line of this whole track.
Greedy's Failure Is DP's Cue
A specific, reliable signal: you reach for a greedy solution ('always take the locally best option') and it gives wrong answers on some inputs. Coin change with coins {1, 3, 4} making 6: greedy grabs 4, then 1, then 1 = three coins, but 3+3 = two coins is better. Greedy commits to a local choice and can't reconsider; DP considers all choices but caches so it stays efficient. When you catch greedy being wrong — or even suspect it might be — that's the moment to define a state and reach for DP. (The next track studies exactly when greedy is safe versus when it isn't.)