Complexity budget

TotalFeasible

State shape by problem type

Problem smells likeState
a prefix decisiondp[i]
two sequencesdp[i][j]
a contiguous rangedp[l][r]
items with a budgetdp[i][w]
a subtreedp[v], often dp[v][0/1]
a subset ()dp[mask]
digits of a numberdp[pos][tight][started][...]
a grid filled cell by celldp[row][profile]
a position with a last choicedp[i][last]
an amount of a resource useddp[i][used]

Optimisation lookup

TransitionRequirementTechniqueResult
over a fixed windownonemonotone queue
over an arbitrary rangenonesegment tree
linear in CHT / Li Chao /
monotone argminD&C DP
quadrangle inequalityKnuth
”exactly groups”, hugeconvex in Aliens trick
value is a convex functionconvexityslope trick
linear, constant transition, huge linearitymatrix power
boolean feasibilitybitset
sum over all submasksSOS DP
row minima, totally monotoneMongeSMAWK

Loop-direction rules

DPDirection
0/1 knapsack, 1D arrayweight decreasing
Unbounded knapsack, 1D arrayweight increasing
Interval DPby increasing length
dp[l][r] from dp[l+1][r] decreasing
Tree DPpost-order (or reverse BFS order)
Bitmask DPmask increasing
Coin change combinationscoin loop outside
Coin change permutationsamount loop outside

Debugging checklist

  1. Is the state complete? Does anything outside the state affect the future?
  2. Is the state minimal? Is any dimension never actually used?
  3. Base cases: are unreachable states initialised to rather than 0?
  4. Loop order: does every dependency precede its use?
  5. Overflow: is long long needed? Are you taking % MOD after every addition and multiplication?
  6. Off by one: is dp[i] “first elements” or “up to index ”? Pick one and stay consistent.
  7. Multiple test cases: is everything reset?
  8. Recursion depth: could the memoised version overflow the stack?
  9. Answer extraction: is it dp[n], or the max over the last row?

Sanity checks before submitting

  • Run the DP against a brute force on random small inputs. This catches almost everything.
  • Test , , all-equal values, and the maximum constraint.
  • If the answer should be non-negative and your sentinel is , check that adding to it never underflows.

When DP is the wrong tool

SymptomTry instead
States depend on each other cyclicallyDijkstra / Bellman-Ford
An exchange argument worksgreedy
”Minimise the maximum”binary search the answer
Matching or assignment structurematching / flow
The state is a set with no small summarymeet in the middle
Counting with independent partscombinatorics / generating functions

See also: Dynamic Programming · Designing States · Complexity Cheatsheet