Optimal substructure
An optimal choice contains optimal choices for the subproblems it creates.
Algorithms Ā· Optimization
Dynamic programming solves each subproblem once and stores the result. Matrix Chain Order makes the method especially visible: the optimal cost emerges by filling two triangular tables one diagonal at a time.
Splitting a problem is not enough. Dynamic programming helps when many recursive paths ask for the same subproblems and a globally optimal solution can be assembled from optimal smaller solutions.
An optimal choice contains optimal choices for the subproblems it creates.
Naive recursion recomputes the same states. Storing them removes that repetition.
Define exactly what a cell represents and which decision reduces it to smaller states.
Start from the full problem, recurse and cache each result on first visit. Only requested states are evaluated.
Start from base cases and fill a table in an order that makes every dependency available. MatrixChainOrder uses this approach.
Matrix multiplication is associative, so every parenthesization produces the same final matrix. The number of scalar multiplications can change dramatically. We are not multiplying the matrices: we are choosing the least expensive order.
10Ā·30Ā·5 + 10Ā·5Ā·60 = 4 500
30Ā·5Ā·60 + 10Ā·30Ā·60 = 27 000
A chain of n matrices is described by the vector p[0ā¦n]: Aįµ¢ has dimensions p[iā1] Ć p[i].
m[i,j] is the minimum number of scalar multiplications needed to compute Aįµ¢ā¦Aā±¼. s[i,j] stores the value of k that achieves that minimum.
Chains of length 1 cost zero. For a longer chain, try every last split k: the left cost, the right cost and the cost of multiplying the two results.
As in the board diagram, the base-case diagonal sits at the bottom. Each new diagonal moves up one level: when a cell is evaluated, every cell it depends on is already filled.
Play the animation to compare splits.
Optimal cost: ā
M stores the optimal value but not the choices that produced it. S stores each split: starting from s[1,n], recursively reconstruct Aāā¦Aā and then Aāāāā¦Aā.
Print(i,j) ā if i = j print Aįµ¢; otherwise print ā(ā, Print(i,s[i,j]), Print(s[i,j]+1,j), ā)ā.
When evaluating m[i,j], every parenthesization has one final multiplication splitting the chain into Aįµ¢ā¦Aā and Aāāāā¦Aā±¼ for a unique k. By optimal substructure, if either side were not optimal, replacing it would improve the global solution. Trying every k and taking the minimum is therefore sufficient.
| Resource | Cost | Why |
|---|---|---|
| Subproblems | Ī(n²) | One cell for each interval [i,j]. |
| Time | Ī(n³) | Up to nā1 splits are tried for each interval. |
| Space | Ī(n²) | The two triangular tables M and S. |
| Reconstruction | Ī(n) | The parenthesization contains n matrices and nā1 splits. |