Advanced 3 min · March 05, 2026

Rod Cutting Problem — O(2^n) Crashes After n=35

Recursive rod cutting crashed pricing engine at length 40 with StackOverflowError, 30-second delays from length 20.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
Quick Answer
  • Rod cutting: maximize revenue by cutting a rod of length n into pieces sold at given prices per length
  • dp[i] = maximum revenue for rod length i; recurrence: dp[i] = max(dp[i], price[j] + dp[i-j]) for j=1..i
  • Optimal substructure: the best cut at length j leaves a sub-problem of length i-j that must also be optimal
  • Time O(n²), Space O(n) — can be reduced to O(n) space with bottom-up tabulation
  • Production gotcha: Recursive without memoization hits O(2^n) — stack overflows at n≈40; always use DP

Every compiler that packs instructions into cache lines, every stock trader slicing a large order into smaller trades, every furniture manufacturer deciding how to cut timber to minimize waste — they're all solving variations of the same fundamental optimization question: given a resource you can divide, what's the most valuable partition? The rod cutting problem is the canonical formulation of that question, and it sits at the intersection of combinatorics and optimization in a way that makes it a perfect vehicle for understanding dynamic programming at depth.

What is Rod Cutting? — Plain English

The Rod Cutting problem: given a rod of length n and a price table where price[i] is the value of a piece of length i, determine the maximum revenue obtainable by cutting the rod and selling the pieces. Pieces can be sold in any combination. You choose how many cuts to make and where.

Example: a rod of length 4 with prices [0, 2, 5, 7, 8] (price[1]=2, price[2]=5, price[3]=7, price[4]=8). Selling as two pieces of length 2 yields 5+5=10, better than the unsplit price of 8.

How Rod Cutting Works — Step by Step

Define dp[i] = maximum revenue from a rod of length i.

  1. dp[0] = 0 (zero-length rod has zero value).
  2. For each length i from 1 to n:
  3. For each first cut at length j from 1 to i:
  4. dp[i] = max(dp[i], price[j] + dp[i - j])
  5. (price[j] is the value of selling a piece of length j; dp[i-j] is the optimal value of the remainder)
  6. Return dp[n].

Time: O(n^2). Space: O(n).

Worked Example — Tracing the Algorithm

Rod length n=4. Prices: price[1]=2, price[2]=5, price[3]=7, price[4]=8.

dp[0]=0.

dp[1]: try j=1: price[1]+dp[0]=2+0=2. dp[1]=2.

dp[2]: try j=1: price[1]+dp[1]=2+2=4. try j=2: price[2]+dp[0]=5+0=5. dp[2]=max(4,5)=5.

dp[3]: try j=1: price[1]+dp[2]=2+5=7. try j=2: price[2]+dp[1]=5+2=7. try j=3: price[3]+dp[0]=7+0=7. dp[3]=7.

dp[4]: try j=1: price[1]+dp[3]=2+7=9. try j=2: price[2]+dp[2]=5+5=10. try j=3: price[3]+dp[1]=7+2=9. try j=4: price[4]+dp[0]=8+0=8. dp[4]=max(9,10,9,8)=10.

Maximum revenue for length-4 rod = 10 (cut into two pieces of length 2).

Implementation — Java

The following Java implementation demonstrates rod cutting with both top-down memoization and bottom-up tabulation. The code is ready for production use with proper edge case handling.

Reconstructing the Cuts — Which Pieces to Sell

The DP only tells you the maximum revenue, not which cuts yield it. To know the actual cutting plan, maintain a 'firstCut' array where firstCut[i] stores the length of the first piece in the optimal solution for rod length i. After computing dp, trace back from n to 0.

Algorithm: 1. Initialize firstCut[0] = 0. 2. In the inner loop, when dp[i] is updated with price[j] + dp[i-j], record firstCut[i] = j. 3. To reconstruct: start at i = n, while i > 0: print firstCut[i]; i -= firstCut[i].

For the example: firstCut[1]=1, firstCut[2]=2, firstCut[3]=1 (or 3, tie-breaking can go to any), firstCut[4]=2. Tracing: i=4 → cut length 2, i=2 → cut length 2, i=0 stop. Pieces: [2,2].

Variations and Production Considerations

Rod cutting is a direct analog of the unbounded knapsack problem: each piece length is an 'item' with weight = length and value = price, and you can take unlimited copies (since multiple pieces of the same length are allowed).

Variations you'll encounter
  • Cutting costs: subtract a fixed cost per cut (except when no cut is made).
  • Length limits: some piece lengths may be unavailable (set price[j] = -inf).
  • Minimum piece length: only sell pieces of at least L (modify inner loop range).
  • Multiple rods: maximize total revenue from a set of rods (2D DP).

Production pattern: When the price list follows a known function (e.g., linear with discounts for longer pieces), the DP can be replaced with a greedy algorithm or a formula — test for this before using DP blindly.

Rod Cutting vs Related DP Problems
ConceptUse CaseExample
Rod Cutting ProblemCore usageSee code above
Unbounded KnapsackItem can be used multiple timesrod cutting with weight = length, value = price
0/1 KnapsackEach item used at most onceinner loop j goes from 1 to n, but dp[i][w] 2D table
Coin Change (min coins)Minimize number of coins to reach sumdp[i] = min(dp[i], 1 + dp[i - coin])
Rod Cutting with Cut CostEach cut reduces total revenuedp[i] = max(price[i], max_{j=1..i-1} price[j] + dp[i-j] - C)

Key Takeaways

  • Rod cutting finds the maximum revenue by choosing how to cut a rod into pieces.
  • dp[i] = max revenue for rod of length i. Recurrence: max over all first-cut lengths j.
  • This is equivalent to unbounded knapsack where cut lengths are reusable items.
  • Time: O(n^2). Space: O(n).
  • Track a 'cuts' array to reconstruct which cuts produce the optimal revenue.
  • Production rule: always benchmark with max expected N; naive recursion is dangerous.

Common Mistakes to Avoid

  • Memorising syntax before understanding the concept
    Symptom: Unable to derive the recurrence relation during interviews; follows template but can't handle variations like cut costs or length limits.
    Fix: Focus on the intuition: dp[i] = maximum over all first-cut lengths j of (revenue from selling that piece + optimal revenue from remaining length). Draw the recursion tree for n=4.
  • Skipping practice and only reading theory
    Symptom: Stuck when the problem statement changes slightly (e.g., 'sell pieces in a specific order' or 'cutting costs apply').
    Fix: Implement rod cutting from scratch in a language you know well. Then modify: add cut cost, change to allow only certain piece lengths, then implement reconstruction. Write at least three variations.
  • Using recursion without memoization
    Symptom: StackOverflowError for n as low as 40, or exponential runtime making the program unusable.
    Fix: Always add memoization or use bottom-up DP. The naive recursive solution has O(2^n) time. Even with memoization, the stack depth is O(n) which can overflow for n > 10^4.
  • Off-by-one in price array indexing
    Symptom: Results are incorrect: for n=4, returns 9 instead of 10 because price[2] is read as index 2 but the real value is at index 3, or price[0] is used for length 1.
    Fix: Ensure price array is 1-indexed where price[i] corresponds to length i piece. If input is 0-indexed (price[0]=2 for length 1), use price[j-1] in the recurrence.

Interview Questions on This Topic

  • QWhat is the recurrence relation for the rod cutting DP?SeniorReveal
    Let price[i] be the value of a piece of length i, and dp[i] be the maximum revenue from a rod of length i. The recurrence is: dp[i] = max_{1 ≤ j ≤ i} (price[j] + dp[i-j]) with base case dp[0] = 0. This considers cutting off a piece of length j and then optimally solving the remaining length i-j.
  • QHow is rod cutting similar to the unbounded knapsack problem?Mid-levelReveal
    Rod cutting is exactly the unbounded knapsack problem where the knapsack capacity is the rod length n, each item (piece length) has weight = length and value = price, and you can take unlimited copies of each item. The DP formulation is identical: iterate over capacity from 1 to n, and for each capacity try every item that fits.
  • QHow would you reconstruct the actual cuts from the DP table?Mid-levelReveal
    Maintain an auxiliary array firstCut[i] that stores the length j that gave the optimal dp[i] during the max comparison. After computing dp, start at i = n and repeatedly apply: output firstCut[i] as a piece length, then set i = i - firstCut[i] until i reaches 0. This yields the list of piece lengths in the optimal cutting plan.
  • QWhat are the time and space complexities of the bottom-up DP solution?JuniorReveal
    Time: O(n^2) because for each rod length i (1..n), we iterate j from 1 to i, giving roughly n(n+1)/2 operations. Space: O(n) for the dp array. The memoized version also uses O(n) space for the memo array but has same O(n^2) time in the worst case due to recomputation of subproblems.
  • QHow would you modify the rod cutting recurrence if each cut costs C dollars (except no cut costs nothing)?SeniorReveal
    The modified recurrence becomes: dp[i] = max(price[i], max_{j=1}^{i-1} (price[j] + dp[i-j] - C)). The first option is selling the whole rod without cutting (no cost). The second option cuts a piece of length j, which incurs a cut cost C, then optimally cuts the remainder. Note that when you cut off j, you pay C once for that cut; the remainder may be cut further and incur additional costs. The recurrence ensures each cut costs C.

Frequently Asked Questions

How is rod cutting related to the unbounded knapsack problem?

Rod cutting is identical to unbounded knapsack where each possible cut length is an 'item' that can be reused. The rod length is the capacity, the cut length is the item weight, and the price is the value. The DP formulation and iteration direction are the same.

How do you find the actual cuts, not just the maximum value?

Track a 'cuts' array where cuts[i] stores the first cut length that achieves dp[i]. To reconstruct: start at length n, read cuts[n] to get the first piece, subtract it, then repeat until length 0.

What if cut costs are involved?

Add a fixed cost for each cut. dp[i] = max over j from 1 to i of (prices[j] + dp[i-j] - cut_cost if i-j > 0 else prices[j]). The cut cost only applies when you actually make a cut (i.e., i-j > 0), not when you sell the whole rod unsplit.

Can rod cutting be solved with a greedy algorithm?

No, because prices are arbitrary. A greedy approach (always pick the piece with highest price/length ratio) fails for counterexamples. For instance, prices [0, 1, 10] for lengths 1 and 2: greedy for n=2 picks length 1 (ratio 1.0) twice = 2, but optimal is a single length-2 piece = 10. DP is necessary.

What is the space-optimized version of the DP?

The recurrence only depends on dp[0..i-1], so you can use a single array of size n+1. No further space reduction is possible because you need all previous values. However, you can reduce to O(1) if the price function is convex (using monotonic queue), but that's a rare case.

🔥

That's Dynamic Programming. Mark it forged?

3 min read · try the examples if you haven't

Previous
Edit Distance Problem
9 / 15 · Dynamic Programming
Next
Fibonacci with DP