Dynamic Programming: The Four Steps
The Four-Step Methodology
Applying dynamic programming to a problem follows a standard pattern:
- Characterise the structure of an optimal solution.
- Recursively define the value of an optimal solution (the Bellman equation).
- Compute the value, typically bottom-up (or top-down with memoisation).
- Reconstruct the optimal solution from the computed table (if required, using backpointers).
Example: Virtual Machine Hosting Problem (Rod Cutting)
Given CPU cores and a price table for a VM with cores, find the maximum revenue achievable by partitioning cores into VMs.
Step 1: Characterise the optimal structure
An optimal partition for cores cuts off a VM of some size (earning ) and optimally partitions the remaining cores. The first cut must be optimal for its remainder.
Step 2: Recursive definition (Bellman equation)
Let be the maximum revenue from cores:
Step 3: Compute bottom-up
m[0] = 0
for j = 1 to n:
m[j] = max(p[i] + m[j-i] for i = 1 to j)
return m[n]
time, space. Each is computed once using lookups into already-computed smaller entries. The naive recursive version would be exponential.
Step 4: Reconstruct the solution
Store the choice of that achieved the maximum at each : choice[j] = i. To reconstruct, start at , output choice[j], subtract it, and repeat until zero.
Example: Weight-Independent Interval Scheduling
Given intervals , maximise the number of non-overlapping intervals selected.
Step 1: Characterise
Sort intervals by finish time. An optimal schedule either includes the last interval (in which case it cannot include any interval overlapping with ) or excludes .
Step 2: Recursive definition
Let be the largest index such that interval does not overlap with interval (i.e. ). Define:
Step 3: Compute
for sorting by finish time, then to fill the DP table after precomputing all .
Step 4: Reconstruct
Trace back: if , skip interval . Otherwise include and jump to .
Extracting the Programme
When computing the maximum in Step 3, also record which action achieved it. After filling the table, start from the original problem state and follow the recorded optimal actions to reconstruct the solution. This is equivalent to storing backpointers in a graph of states.
If multiple actions yield the same optimal value, any may be chosen; the problem asks for an optimal solution, not the unique optimal solution.
Summary
| Step | Task |
|---|---|
| 1 | Characterise optimal structure |
| 2 | Write Bellman equation (recursive definition) |
| 3 | Compute value bottom-up (or memoised top-down) |
| 4 | Reconstruct solution via backpointers |
| Key insight | Identify states that maximise subproblem overlap |
| Common pitfalls | Exponential without memoisation; wrong state formulation causes poor overlap |