Cut a rod for the most money
A piece of rod of length L (1 ≤ L ≤ prices.length) sells for prices[L − 1]. Given a rod of
length n, cut it into pieces whose lengths each appear in the price list and return the largest total
revenue. Pieces may have equal lengths, and the whole rod may be sold as one piece if its length is listed.
Examples
| Input | Output | Why |
|---|---|---|
prices = [1,5,8,9,10,17,17,20], n = 8 | 22 | 2 + 6: 5 + 17. |
prices = [3,5,8,9,10,17,17,20], n = 8 | 24 | Eight pieces of length 1. |
prices = [2], n = 5 | 10 | Only length 1 can be sold. |
Constraints
- 1 ≤ prices.length ≤ 1000
- 0 ≤ n ≤ 1000
- 1 ≤ prices[i] ≤ 10⁵
Hints
Hint 1
best[t] = the most a rod of length t can earn.
Hint 2
best[t] = max over the first piece L ≤ min(t, prices.length) of prices[L − 1] + best[t − L].
Hint 3
best[0] = 0; fill t upwards.
Where people lose marks
- Greedy by price per unit length, which fails when the best ratio does not divide n.
- Indexing prices by length instead of length − 1.
Dry run on [1,5,8,9,10,17,17,20],8
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 8best0011
Length 1: first piece 1 (1) + best[0] = 1.
-
Step 2 / 8best001152
Length 2: first piece 2 (5) + best[0] = 5.
-
Step 3 / 8best00115283
Length 3: first piece 3 (8) + best[0] = 8.
-
Step 4 / 8best00115283104
Length 4: first piece 2 (5) + best[2] = 10.
-
Step 5 / 8best00115283104135
Length 5: first piece 2 (5) + best[3] = 13.
-
Step 6 / 8best00115283104135176
Length 6: first piece 6 (17) + best[0] = 17.
-
Step 7 / 8best00115283104135176187
Length 7: first piece 1 (1) + best[6] = 18.
-
Step 8 / 8best00115283104135176187228
Length 8: first piece 2 (5) + best[6] = 22.
How to think about it
Lengths can repeat, so this is the unbounded knapsack: best[t] = max over L of prices[L − 1] + best[t − L],
trying every length for the first piece, with best[0] = 0. Each entry reads only shorter rods, so fill upwards.
Only lengths that appear in the list may be sold, which here means L ≤ prices.length.
Complexity. Time O(n · prices.length) · Space O(n)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def cut_rod(prices, n):
best = [0] * (n + 1) # best[t]: most a rod of length t earns
for t in range(1, n + 1):
for L in range(1, min(t, len(prices)) + 1):
best[t] = max(best[t], prices[L - 1] + best[t - L]) # first piece of length L
return best[n]#include <algorithm>
#include <vector>
long long solve(const std::vector<int>& prices, int n) {
std::vector<long long> best(n + 1, 0);
for (int t = 1; t <= n; ++t)
for (int L = 1; L <= std::min(t, (int)prices.size()); ++L)
best[t] = std::max(best[t], prices[L - 1] + best[t - L]); // first piece of length L
return best[n];
}class Solution {
public long cutRod(int[] prices, int n) {
long[] best = new long[n + 1];
for (int t = 1; t <= n; t++)
for (int L = 1; L <= Math.min(t, prices.length); L++)
best[t] = Math.max(best[t], prices[L - 1] + best[t - L]); // first piece of length L
return best[n];
}
}function cutRod(prices, n) {
const best = new Array(n + 1).fill(0);
for (let t = 1; t <= n; t++)
for (let L = 1; L <= Math.min(t, prices.length); L++) best[t] = Math.max(best[t], prices[L - 1] + best[t - L]);
return best[n];
}fn solve(prices: &[i64], n: i64) -> i64 {
let n = n as usize;
let mut best = vec![0i64; n + 1];
for t in 1..=n {
for l in 1..=t.min(prices.len()) {
best[t] = best[t].max(prices[l - 1] + best[t - l]); // first piece of length l
}
}
best[n]
}import Data.Array
solve :: [Int] -> Int -> Int
solve prices n = best ! n
where
p = listArray (1, length prices) prices
best = listArray (0, n) (0 : [maximum [p ! l + best ! (t - l) | l <- [1 .. min t (length prices)]] | t <- [1 .. n]]) :: Array Int Int
Variants to try
- Each cut costs a fixed amount: subtract it per extra piece.
- Return the cuts.
- Each length may be cut at most k times (bounded).
Next problems
Fewest coins to make an amount
Greedy fails, recursion repeats itself, and one array fixes both. The cleanest first dynamic programme.
Open the problem → Medium15 minSplit an integer for the largest product
Write n as a sum of at least two positive integers and maximise their product. Parts can repeat: an unbounded knapsack over part sizes.
Open the problem → Easy10 minThe cheapest way up a staircase
Each step has a cost; climb one or two steps at a time; start on step 0 or 1. Return the cheapest way past the top.
Open the problem →Write a solution and run it against the real test table.
Keep going
Fewest coins to make an amount
Greedy fails, recursion repeats itself, and one array fixes both. The cleanest first dynamic programme.
Open the problem → Medium15 minSplit an integer for the largest product
Write n as a sum of at least two positive integers and maximise their product. Parts can repeat: an unbounded knapsack over part sizes.
Open the problem → Easy10 minThe cheapest way up a staircase
Each step has a cost; climb one or two steps at a time; start on step 0 or 1. Return the cheapest way past the top.
Open the problem → Dynamic programmingThe pattern behind it
Write the recursion, notice the repeats, fill a table in an order that makes each entry final.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.