CMD Guide
HomeDSADynamic Programming

Rod Cutting

Rod cutting works by exploiting the fact that the best way to cut a rod of length n is to pick some first-piece length i (1≤i≤n), sell it for price[i], and then optimally cut the remaining rod of length n-i — a smaller instance of the exact same problem — so the optimal value combines a choice with a recursively optimal subproblem, which is the signature of dynamic programming.

Recognize the pattern

Brute force to optimal

Brute force: for a rod of length n, try every first cut length i from 1..n and recurse on n-i, taking the max. This is the recurrence cut(n) = max over i in [1,n] of price[i] + cut(n-i), with cut(0) = 0. Because cut(n-i) is recomputed from scratch for overlapping subproblem sizes, this branches like a full recursion tree: cost is exponential, roughly O(2^n).

Optimal: memoize (top-down) or tabulate (bottom-up) on the single parameter n, since the subproblem is fully described by remaining length. There are only n+1 distinct subproblems (lengths 0..n), each solved once in O(n) work (trying every cut), giving O(n^2) total.

Complexity from first principles

Time: there are n+1 distinct states (dp[0..n]). Computing dp[len] requires trying every cut i from 1 to len, i.e. up to len iterations. Total work = ∑len=1n len = n(n+1)/2 = O(n2). Each iteration does O(1) arithmetic, so no hidden log factors.

Space: dp array of size n+1 → O(n). (If you also track the chosen first-cut per length to reconstruct the actual pieces, that's another O(n) array — still O(n) total.) No extra space needed beyond that; the bottom-up loop uses O(1) auxiliary space per state.

Worked example

price = [_, 2, 6, 7, 10, 13] (1-indexed by length), n = 5. This is a small example adapted for illustration, not CLRS's own price table (CLRS uses n=10 with price=[1,5,8,9,10,17,17,20,24,30]) — the recurrence and mechanism are identical either way. Bottom-up: dp[len] = max over i=1..len of price[i] + dp[len-i].

lenbest split (i, dp[len-i])dp[len]
00
1i=1: 2+dp[0]=22
2i=1: 2+dp[1]=4; i=2: 6+dp[0]=66
3i=1: 2+dp[2]=8; i=2: 6+dp[1]=8; i=3: 7+dp[0]=78
4i=1: 2+dp[3]=10; i=2: 6+dp[2]=12; i=3: 7+dp[1]=9; i=4: 10+dp[0]=1012
5i=1: 2+dp[4]=14; i=2: 6+dp[3]=14; i=3: 7+dp[2]=13; i=4: 10+dp[1]=12; i=5: 13+dp[0]=1314

dp[5] = 14, matching the brute-force check (two pieces of length 2 + one of length 1: 6+6+2=14).

Java implementation (bottom-up, with reconstruction)

public class RodCutting {
    // price[i] = price of a piece of length i (1-indexed); price[0] unused.
    public static int maxProfit(int[] price, int n) {
        int[] dp = new int[n + 1];
        int[] cut = new int[n + 1]; // first-cut length chosen at each len
        for (int len = 1; len <= n; len++) {
            int best = Integer.MIN_VALUE, bestI = -1;
            for (int i = 1; i <= len; i++) {
                int candidate = price[i] + dp[len - i];
                if (candidate > best) {
                    best = candidate;
                    bestI = i;
                }
            }
            dp[len] = best;
            cut[len] = bestI;
        }
        // Optional: reconstruct pieces
        int len = n;
        StringBuilder pieces = new StringBuilder();
        while (len > 0) {
            pieces.append(cut[len]).append(" ");
            len -= cut[len];
        }
        System.out.println("Pieces: " + pieces.toString().trim());
        return dp[n];
    }
}

Go implementation (bottom-up, with reconstruction)

package main

import "fmt"

// price[i] = price of a piece of length i (1-indexed); price[0] unused.
func maxProfit(price []int, n int) int {
	dp := make([]int, n+1)
	cut := make([]int, n+1) // first-cut length chosen at each len
	for length := 1; length <= n; length++ {
		best, bestI := -1<<31, -1
		for i := 1; i <= length; i++ {
			candidate := price[i] + dp[length-i]
			if candidate > best {
				best = candidate
				bestI = i
			}
		}
		dp[length] = best
		cut[length] = bestI
	}
	// Optional: reconstruct pieces
	pieces := []int{}
	for length := n; length > 0; length -= cut[length] {
		pieces = append(pieces, cut[length])
	}
	fmt.Println("Pieces:", pieces)
	return dp[n]
}

Pitfalls

When to use / when not — trade-offs

Use bottom-up O(n^2) DP whenever the rod length n is the state and cuts are unbounded/reusable — it's simple, iterative, and avoids recursion overhead. Compare against:

Takeaways

Recall: Why is rod cutting solvable with just an O(n) dp array instead of a 2D table like 0/1 knapsack?


Adapted from CLRS (Cormen, Leiserson, Rivest, Stein), "Introduction to Algorithms", Ch. 15 (Dynamic Programming) — Rod Cutting section; standard unbounded-knapsack DP formulation. Worked-example price values are adapted for a compact walkthrough, not CLRS's own table.

🤖 Don't fully get this? Learn it with Claude

Stuck on Rod Cutting? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Rod Cutting** (DSA) and want to truly understand it. Explain Rod Cutting from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Rod Cutting** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Rod Cutting** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Rod Cutting** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes