DP shares equivalent remaining questions
Picture
Different paths through a search can reach the same unfinished problem. Dynamic programming computes its answer once and reuses it. The difficult part is deciding what “same” means: the state must preserve all information that can change legal continuations or their contribution to the answer.
Predict
You are selecting items, each usable once. Two calls have capacity 5 left, but one may still use item 0 while the other has already considered it. Can best(capacity) safely merge them?
Reveal the reasoning
No. Their available choices differ. A typical state is best(item_index, capacity). For unlimited reuse of the same fixed item types, a different recurrence may legitimately need only capacity.
Go deeper: derive a state before drawing a table
Use a state sentence: “ways(r) is the number of move sequences that consume exactly r remaining steps, using moves 1 or 2.” Fixed move rules are shared context. Previous moves do not affect future legality, so r is enough.
from functools import cache
def count_climbs(n):
@cache
def ways(r):
if r == 0:
return 1
if r < 0:
return 0
return ways(r - 1) + ways(r - 2)
return ways(n)
assert count_climbs(5) == 8
assert count_climbs(0) == 1
There are O(n) states and constant transition work per state: O(n) arithmetic operations and O(n) stored answers plus recursion depth. Counting with large integers adds bit-level arithmetic costs.
For an optimization recurrence, explain why the chosen state has optimal substructure: replacing a continuation with a better one for the same state must preserve feasibility and improve or preserve the whole answer. If a hidden history restriction makes the replacement invalid, expand the state.
Counting uses addition over disjoint choices; existence may use any; minimization uses min; maximization uses max. DP is not restricted to optimization. Also, a finite dependency order is needed for these recursive/tabulated DPs: caching completed results does not resolve a cycle of unanswered calls.
Cache keys must be hashable and must include the varying inputs. The nested function keeps this cache scoped to one fixed problem instance; mutating captured inputs while reusing the cache would invalidate its answers.
Analogy limit: DP can share suffix counts, but enumerating full outputs still requires attaching those suffixes to every distinct required prefix.
Change one rule
You receive a bonus only if a size-two move follows a size-one move. Is r sufficient for the best remaining score?
Check the variation
No. The previous move affects the next reward. Store the relevant previous-move information, or derive an equivalent state that preserves that effect.
Connect
Evaluation order comes after the recurrence. Knapsack makes availability explicit. Budget DP adds a coordinate only when its information becomes necessary.