Dynamic programming and Bellman recurrences
Define sufficient states, derive optimal substructure, and evaluate overlapping subproblems in a justified order.
On this page
The question for today
What you’ll understand
- Describe a subproblem with enough information to determine its optimum.
- Derive the include-or-exclude recurrence for weighted interval scheduling.
- Separate state count, transition cost, reconstruction storage, and encoded input length.
When a safe greedy exchange is unavailable, keep several choices alive through smaller optimization problems. Dynamic programming works by giving each subproblem a precise meaning, proving a recurrence for its value, and computing repeated subproblems only once. Its central design choice is the state: histories with the same state must have the same relevant future possibilities. A table is merely a storage device; without that sufficiency argument, filling it can produce a fast answer to the wrong problem.
A state must forget only irrelevant history
Return to weighted interval scheduling, with positive-duration half-open intervals and nonnegative rewards. Sort jobs by finish time and label them one through n. Let p(j) be the greatest earlier index whose job finishes no later than job j starts, or zero if no such index exists. Define V(j) as the largest total reward obtainable using only the first j jobs. This prefix is sufficient because the ordering makes every job compatible with a chosen last job belong to an earlier compatible prefix.
An optimal prefix solution either excludes job j or includes it. Exclusion leaves the first j minus one jobs. Inclusion earns its reward and allows only jobs among the first p(j). Replacing a suboptimal compatible prefix with a better one would improve the full solution, so the included prefix must itself be optimal. The recurrence compares both cases rather than claiming one is always safe. Nonnegative rewards simplify interpretation, although allowing an empty schedule also handles negative rewards by skipping them.
Evaluation order is a dependency proof
All dependencies point to smaller indices, so a bottom-up loop computes V(0), V(1), and onward through V(n). Alternatively, memoized recursion evaluates a value on demand and saves it for later calls. Both methods implement the same recurrence; the dependency structure explains why neither needs to solve a subproblem before its own prerequisites are available. Counting n entries is not enough for a time bound: count the work to determine each p(j) and evaluate each transition too.
After sorting, binary searching the finish times computes each p(j) in logarithmic time, for O(n log n) comparison work overall. Once those indices exist, the recurrence takes O(n) additions and comparisons of rewards. Store a choice or compare the recorded values during backtracking to reconstruct actual jobs. Reporting only V(n) loses the witness schedule. Ties allow several optima; a consistent tie rule produces one witness without implying uniqueness. Exact arithmetic costs depend on the bit lengths of accumulated rewards.
Bellman reasoning has conditions
The principle of optimality says an optimal complete decision sequence contains an optimal continuation for the state it reaches. The state must include every quantity that affects feasibility or future costs. If a budget is omitted, two apparently identical prefixes may have different affordable continuations. If previous choices change a setup cost, recording only the current time may be insufficient. Adding the missing information can repair correctness while greatly increasing the number of states. That increase is a real computational cost, not a bookkeeping inconvenience.
Not every Bellman-looking equation has an immediate one-pass solution. Cyclic state dependencies may require a finite-horizon expansion, repeated relaxation, or a separate fixed-point argument with suitable assumptions. Likewise, an integer-capacity table with W columns takes time polynomial in W, not necessarily in the binary length of W. This is the pseudopolynomial distinction from recurrence analysis. A good dynamic-programming solution therefore presents the state meaning, recurrence proof, base cases, evaluation order, complexity model, and witness recovery as one connected argument.
Work it through
Recover the better weighted schedule
Jobs sorted by finish are A = [0,2), reward 4; B = [1,4), reward 7; C = [2,5), reward 5; D = [4,6), reward 6. Compute the optimum and recover its jobs.
The predecessor indices are p(A) = 0, p(B) = 0, p(C) = 1, and p(D) = 2. Thus V(1) = max(0,4) = 4 and V(2) = max(4,7) = 7.
For C, including it with A earns 5 + 4 = 9, so V(3) = 9. For D, including it with the optimum on the first two jobs earns 6 + 7 = 13, beating V(3).
Backtrack from D to prefix two, where B was selected, then to zero. B finishes at 4 and D starts at 4, so their combination is feasible under the half-open convention.
The optimum reward is 13 from B and D. The prefix optimum at C was A and C, illustrating why a later optimum can abandon an earlier witness while reusing its recorded value.
The living notebook
Explore the model
Interactive lab · cache
Repeated states need usable storage
Pause and reset, then set both controls to capacity 4 and stride 4. Predict four cold misses followed by hits for the four-address cycle; inspect the initial sixteen requests. For a fresh comparison, pause and reset, then set capacity 3 and stride 4. Predict sixteen misses because each address is evicted before reuse. This LRU cache illustrates why repeated requests do not guarantee a saved result remains available. It is not the weighted-interval recurrence or a simulation of unbounded memoization; the dependency proof and table values are supplied by the lesson.
- Hits / requests
- 0 / 16
- Hit rate
- 0%
- Address-stream period
- 16 addresses
A fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forMemoization's evaluate-once bound assumes retained results and lookup costs that match the analysis.
Pause & reason
Check your understanding
Your turn
Try it yourself
For jobs A = [0,3), reward 5; B = [1,4), reward 6; C = [3,5), reward 4; D = [5,7), reward 3, compute all four prefix values and one optimal schedule.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
C can follow A but cannot follow B. D can follow every earlier job, so its predecessor is the third prefix.
Compare with the solution
The predecessors are 0,0,1,3. Starting from V(0) = 0 gives V(1) = 5, V(2) = 6, V(3) = max(6,4 + 5) = 9, and V(4) = max(9,3 + 9) = 12. Backtracking selects D, then C, then A. Their endpoints meet at 3 and 5, so the schedule A,C,D is feasible and earns twelve. The recurrence proves no excluded alternative can improve that value because it considers both exhaustive final-job cases at every prefix.
Keep the idea
Take it with you
- A correct state preserves exactly the history needed for future decisions.
- A recurrence needs exhaustive choices and a proof that optimal subproblems can replace weaker ones.
- State count, transition work, preprocessing, arithmetic, and witness recovery all contribute to complexity.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.