Problem. A rod of length can be cut into integer pieces. A piece of length sells for . Maximise the total revenue.
The DP β
long long rodCutting(int n, const vector<long long>& p) { // p[1..n]
vector<long long> dp(n + 1, 0);
for (int len = 1; len <= n; len++)
for (int i = 1; i <= len; i++)
dp[len] = max(dp[len], p[i] + dp[len - i]);
return dp[n];
}This is unbounded knapsack in disguise: items are the piece lengths, weights are the lengths, values are the prices, and the capacity is . Written that way it is for distinct lengths.
for (int i = 1; i <= k; i++)
for (int len = length[i]; len <= n; len++) // UPWARD: unlimited copies
dp[len] = max(dp[len], dp[len - length[i]] + price[i]);Reconstruction
vector<int> cut(n + 1, 0); // first piece length
// during the DP: if improved, cut[len] = i;
int len = n;
while (len > 0) { pieces.push_back(cut[len]); len -= cut[len]; }Variants
| Variant | Change |
|---|---|
| Rod cutting | unbounded knapsack |
| Cost per cut | |
| At most pieces | add a dimension, |
| Each length usable once | 0/1 knapsack β weight loop downward |
| Maximise the product of piece lengths | see below |
| Cutting sticks (given cut positions) | interval DP, |
| 2D cutting stock | much harder; NP-hard |
Maximum product of piece lengths
βCut into positive integers maximising their product.β
The answer is to use as many 3s as possible, with the remainder handled specially:
| Pieces | |
|---|---|
| 0 | all 3s |
| 1 | one 4 (or two 2s), rest 3s β never a 1 |
| 2 | one 2, rest 3s |
Why: , so 3 is the most βefficientβ piece per unit length; and is always wasteful ( combined). The continuous optimum is , and 3 is the nearest integer.
long long maxProduct(int n) {
if (n <= 3) return n - 1; // special small cases
if (n % 3 == 0) return ipow(3, n / 3);
if (n % 3 == 1) return 4 * ipow(3, (n - 4) / 3);
return 2 * ipow(3, (n - 2) / 3);
}Cutting sticks β the interval-DP cousin
βA stick of length must be cut at given positions. Each cut costs the length of the piece being cut. Minimise the total cost.β
with the cut positions (plus 0 and ) as the endpoints. , or with Knuth optimization since the cost satisfies the quadrangle inequality.
This is the same recurrence as matrix chain multiplication and merging stones β a good illustration that interval DP is one pattern wearing several costumes.
Why it is worth knowing
Rod cutting is usually the first DP anyone meets after Fibonacci, and it teaches two things:
- Recognising a known problem in disguise β it is unbounded knapsack, and seeing that immediately gives the form and all its variants.
- The loop direction encodes the semantics β upward for unlimited copies, downward for one each. Same three lines, different problem.
See also: Knapsack Β· Interval DP Β· Matrix Chain Multiplication