"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 counterexample disproves that particular greedy rule; it does not prove DP is the only alternative. Coin change with {1,3,4} and amount 6 is a case where amount-state DP works well. For another problem, a different greedy rule, graph algorithm, or search method may be right, so verify overlap and state structure separately.