Rod Cutting

Last Updated : 23 Oct, 2026

Given a rod of length n inches and an array price[], where price[i] denotes the value of a piece of length i (1-based Index). Determine the maximum value obtainable by cutting up the rod and selling the pieces.

Note: The value of n is equal to the size of price array.

Examples:

Input: price[] = [1, 5, 8, 9, 10, 17, 17, 20]
Output: 22
Explanation: The maximum obtainable value is 22 by cutting in two pieces of lengths 2 and 6, i.e., 5 + 17 = 22.

Input: price[] = [3, 5, 8, 9, 10, 17, 17, 20]
Output: 24
Explanation: The maximum obtainable value is 24 by cutting the rod into 8 pieces of length 1, i.e, 8 *price[1] = 8 * 3 = 24.

Input: price[] = [3]
Output: 3
Explanation: There is only 1 way to pick a piece of length 1.

Try It Yourself
redirect icon

[Naive Approach] Recursion - O(2 ^ n) Time and O(n) Space

  • For a rod of length i, try all possible cuts j (1 ≤ j ≤ i).
  • For each cut, add the price of length j with the best profit of remaining rod (i − j).
  • Take the maximum profit among all possible cuts.
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int cutRodRecur(int i, vector<int> &price)
{
    // Base case
    if (i == 0)
        return 0;

    int res = 0;

    // Try every possible first cut
    for (int j = 1; j <= i; j++)
    {
        res = max(res, price[j - 1] + cutRodRecur(i - j, price));
    }

    return res;
}

int cutRod(vector<int> &price)
{
    return cutRodRecur(price.size(), price);
}

int main()
{
    vector<int> price = {1, 5, 8, 9, 10, 17, 17, 20};

    cout << cutRod(price);
    return 0;
}
Java
import java.util.Arrays;

public class GFG {
    // Recursive function to return the maximum obtainable
    // value
    static int cutRodRecur(int i, int[] price)
    {
        // Base case
        if (i == 0)
            return 0;

        int res = 0;

        // Try every possible first cut
        for (int j = 1; j <= i; j++) {
            res = Math.max(res,
                           price[j - 1]
                               + cutRodRecur(i - j, price));
        }

        return res;
    }

    static int cutRod(int[] price)
    {
        return cutRodRecur(price.length, price);
    }

    public static void main(String[] args)
    {
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };

        System.out.println(cutRod(price));
    }
}
Python
def cutRodRecur(i, price):
    # Base case
    if i == 0:
        return 0

    res = 0

    # Try every possible first cut
    for j in range(1, i + 1):
        res = max(res, price[j - 1] + cutRodRecur(i - j, price))

    return res

def cutRod(price):
    return cutRodRecur(len(price), price)

if __name__ == '__main__':
    price = [1, 5, 8, 9, 10, 17, 17, 20]
    print(cutRod(price))
C#
using System;

public class GFG {
    // Recursive function to return the maximum obtainable
    // value
    static int cutRodRecur(int i, int[] price)
    {
        // Base case
        if (i == 0)
            return 0;

        int res = 0;

        // Try every possible first cut
        for (int j = 1; j <= i; j++) {
            res = Math.Max(res,
                           price[j - 1]
                               + cutRodRecur(i - j, price));
        }

        return res;
    }

    static int cutRod(int[] price)
    {
        return cutRodRecur(price.Length, price);
    }

    public static void Main()
    {
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };

        Console.WriteLine(cutRod(price));
    }
}
JavaScript
function cutRodRecur(i, price)
{
    // Base case
    if (i === 0)
        return 0;

    let res = 0;

    // Try every possible first cut
    for (let j = 1; j <= i; j++) {
        res = Math.max(
            res, price[j - 1] + cutRodRecur(i - j, price));
    }

    return res;
}

function cutRod(price)
{
    return cutRodRecur(price.length, price);
}

// Driver Code
const price = [ 1, 5, 8, 9, 10, 17, 17, 20 ];
console.log(cutRod(price));

Output
22

Note: This recursive approach gives TLE because it recalculates the same subproblems multiple times, resulting in exponential time complexity.

[Better Approach] Idea of Unbounded Knapsack - O(n ^ 2) Time and O(n ^ 2) Space

This problem can be treated like an Unbounded Knapsack, where each cut length can be used multiple times.

  • For each cut length, we have two choices: take the cut (if it fits) or skip it.
  • We choose the maximum profit from these choices to get the best way to cut the rod.
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int cutRodRecur(int i, int j, vector<int> &price, vector<vector<int>> &dp)
{
    // Base case
    if (i == 0 || j == 0)
        return 0;

    // Return stored result
    if (dp[i][j] != -1)
        return dp[i][j];

    int take = 0;

    // Take a piece of length i
    if (i <= j)
        take = price[i - 1] + cutRodRecur(i, j - i, price, dp);

    // Skip the current piece length
    int noTake = cutRodRecur(i - 1, j, price, dp);

    return dp[i][j] = max(take, noTake);
}

int cutRod(vector<int> &price)
{
    int n = price.size();
    vector<vector<int>> dp(n + 1, vector<int>(n + 1, -1));

    return cutRodRecur(n, n, price, dp);
}

int main()
{
    vector<int> price = {1, 5, 8, 9, 10, 17, 17, 20};
    cout << cutRod(price);
}
Java
import java.util.Arrays;

public class GFG {

    int cutRodRecur(int i, int j, int[] price, int[][] dp)
    {
        // Base case
        if (i == 0 || j == 0)
            return 0;

        // Return stored result
        if (dp[i][j] != -1)
            return dp[i][j];

        int take = 0;

        // Take a piece of length i
        if (i <= j)
            take = price[i - 1]
                   + cutRodRecur(i, j - i, price, dp);

        // Skip the current piece length
        int noTake = cutRodRecur(i - 1, j, price, dp);

        return dp[i][j] = Math.max(take, noTake);
    }

    int cutRod(int[] price)
    {
        int n = price.length;
        int[][] dp = new int[n + 1][n + 1];
        for (int[] row : dp)
            Arrays.fill(row, -1);

        return cutRodRecur(n, n, price, dp);
    }

    public static void main(String[] args)
    {
        GFG rc = new GFG();
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };
        System.out.println(rc.cutRod(price));
    }
}
Python
def cutRodRecur(i, j, price, dp):
    # Base case
    if i == 0 or j == 0:
        return 0

    # Return stored result
    if dp[i][j]!= -1:
        return dp[i][j]

    take = 0

    # Take a piece of length i
    if i <= j:
        take = price[i - 1] + cutRodRecur(i, j - i, price, dp)

    # Skip the current piece length
    noTake = cutRodRecur(i - 1, j, price, dp)

    dp[i][j] = max(take, noTake)
    return dp[i][j]

def cutRod(price):
    n = len(price)
    dp = [[-1 for _ in range(n + 1)] for _ in range(n + 1)]
    return cutRodRecur(n, n, price, dp)

if __name__ == "__main__":
    price = [1, 5, 8, 9, 10, 17, 17, 20]
    print(cutRod(price))
C#
using System;

public class GFG {

    public int CutRodRecur(int i, int j, int[] price,
                           int[, ] dp)
    {
        // Base case
        if (i == 0 || j == 0)
            return 0;

        // Return stored result
        if (dp[i, j] != -1)
            return dp[i, j];

        int take = 0;

        // Take a piece of length i
        if (i <= j)
            take = price[i - 1]
                   + CutRodRecur(i, j - i, price, dp);

        // Skip the current piece length
        int noTake = CutRodRecur(i - 1, j, price, dp);

        return dp[i, j] = Math.Max(take, noTake);
    }

    public int cutRod(int[] price)
    {
        int n = price.Length;
        int[, ] dp = new int[n + 1, n + 1];

        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= n; j++) {
                dp[i, j] = -1;
            }
        }

        return CutRodRecur(n, n, price, dp);
    }

    public static void Main()
    {
        GFG rc = new GFG();
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };
        Console.WriteLine(rc.cutRod(price));
    }
}
JavaScript
function cutRodRecur(i, j, price, dp)
{
    // Base case
    if (i === 0 || j === 0)
        return 0;

    // Return stored result
    if (dp[i][j] !== -1)
        return dp[i][j];

    let take = 0;

    // Take a piece of length i
    if (i <= j)
        take = price[i - 1]
               + cutRodRecur(i, j - i, price, dp);

    // Skip the current piece length
    let noTake = cutRodRecur(i - 1, j, price, dp);

    return dp[i][j] = Math.max(take, noTake);
}

function cutRod(price)
{
    let n = price.length;
    let dp = Array.from({length : n + 1},
                        () => Array(n + 1).fill(-1));

    return cutRodRecur(n, n, price, dp);
}

// Driver Code
let price = [ 1, 5, 8, 9, 10, 17, 17, 20 ];
console.log(cutRod(price));

Output
22

[Expected Approach - 1] Top-Down DP or Memoization - O(n ^ 2) Time and O(n) Space

  • In recursion, the same rod lengths are solved multiple times.
  • Since there are only n possible rod lengths, we store their results in a DP array.
  • If a result is already stored, we reuse it instead of recomputing, improving efficiency.

Working of Approach:

  • If the rod length is 0, return 0.
  • If the result is already stored in dp[i], return it.
  • Try every possible first cut and add its price to the maximum value of the remaining rod.
  • Store and return the maximum value in dp[i].

Let us understand with an example:
Input: price[] = [1, 5, 8, 9, 10, 17, 17, 20]

  • For each rod length i, try every first cut j and calculate price[j - 1] + cutRodRecur(i - j).
  • For length 2, the maximum value is 5; for length 6, it is 17.
  • For length 8, the maximum value is obtained by cutting the rod into lengths 2 and 6, giving 5 + 17 = 22.
  • The computed results are stored in dp to avoid repeated calculations, and the function returns 22.
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int cutRodRecur(int i, vector<int> &price, vector<int> &dp)
{
    // Base case
    if (i == 0)
        return 0;

    // Return stored result
    if (dp[i] != -1)
        return dp[i];

    int res = 0;

    // Try every possible first cut
    for (int j = 1; j <= i; j++)
    {
        res = max(res, price[j - 1] + cutRodRecur(i - j, price, dp));
    }

    return dp[i] = res;
}

int cutRod(vector<int> &price)
{
    int n = price.size();
    vector<int> dp(n + 1, -1);

    return cutRodRecur(n, price, dp);
}

int main()
{
    vector<int> price = {1, 5, 8, 9, 10, 17, 17, 20};
    cout << cutRod(price);
    return 0;
}
Java
import java.util.Arrays;

public class GFG {
    // Function to find the maximum obtainable value
    public static int cutRodRecur(int i, int[] price,
                                  int[] dp)
    {
        // Base case
        if (i == 0)
            return 0;

        // Return stored result
        if (dp[i] != -1)
            return dp[i];

        int res = 0;

        // Try every possible first cut
        for (int j = 1; j <= i; j++) {
            res = Math.max(
                res, price[j - 1]
                         + cutRodRecur(i - j, price, dp));
        }

        return dp[i] = res;
    }

    public static int cutRod(int[] price)
    {
        int n = price.length;
        int[] dp = new int[n + 1];
        Arrays.fill(dp, -1);

        return cutRodRecur(n, price, dp);
    }

    public static void main(String[] args)
    {
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };
        System.out.println(cutRod(price));
    }
}
Python
def cutRodRecur(i, price, dp):
    # Base case
    if i == 0:
        return 0

    # Return stored result
    if dp[i]!= -1:
        return dp[i]

    res = 0

    # Try every possible first cut
    for j in range(1, i + 1):
        res = max(res, price[j - 1] + cutRodRecur(i - j, price, dp))

    dp[i] = res
    return dp[i]

def cutRod(price):
    n = len(price)
    dp = [-1] * (n + 1)
    return cutRodRecur(n, price, dp)

if __name__ == '__main__':
    price = [1, 5, 8, 9, 10, 17, 17, 20]
    print(cutRod(price))
C#
using System;

public class GFG {
    public static int CutRodRecur(int i, int[] price,
                                  int[] dp)
    {
        // Base case
        if (i == 0)
            return 0;

        // Return stored result
        if (dp[i] != -1)
            return dp[i];

        int res = 0;

        // Try every possible first cut
        for (int j = 1; j <= i; j++) {
            res = Math.Max(
                res, price[j - 1]
                         + CutRodRecur(i - j, price, dp));
        }

        return dp[i] = res;
    }

    public static int cutRod(int[] price)
    {
        int n = price.Length;
        int[] dp = new int[n + 1];
        Array.Fill(dp, -1);

        return CutRodRecur(n, price, dp);
    }

    public static void Main()
    {
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };
        Console.WriteLine(cutRod(price));
    }
}
JavaScript
function cutRodRecur(i, price, dp)
{
    // Base case
    if (i === 0)
        return 0;

    // Return stored result
    if (dp[i] !== -1)
        return dp[i];

    let res = 0;

    // Try every possible first cut
    for (let j = 1; j <= i; j++) {
        res = Math.max(res,
                       price[j - 1]
                           + cutRodRecur(i - j, price, dp));
    }

    return dp[i] = res;
}

function cutRod(price)
{
    const n = price.length;
    const dp = Array(n + 1).fill(-1);

    return cutRodRecur(n, price, dp);
}

// Driver Code
const price = [ 1, 5, 8, 9, 10, 17, 17, 20 ];
console.log(cutRod(price));

Output
22

[Expected Approach - 2] Bottom-Up DP or Tabulation - O(n ^ 2) Time and O(n) Space

  • We compute the maximum profit starting from smaller rod lengths and move to larger ones.
  • For a rod of length i, we try all cuts j and (i − j).
  • Since smaller lengths are already solved, we reuse their results to fill the DP table.

Detailed Steps:

  • Initialize dp[0] = 0, as a rod of length 0 has no value.
  • Iterate through each rod length from 1 to n.
  • Try every possible first cut and add its price to the maximum value of the remaining rod.
  • Store the maximum value in dp[i] and return dp[n].
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int cutRod(vector<int> &price)
{
    int n = price.size();
    vector<int> dp(n + 1, 0);

    // Find maximum value for each rod length
    for (int i = 1; i <= n; i++)
    {

        // Try every possible first cut
        for (int j = 1; j <= i; j++)
        {
            dp[i] = max(dp[i], price[j - 1] + dp[i - j]);
        }
    }

    return dp[n];
}

int main()
{
    vector<int> price = {1, 5, 8, 9, 10, 17, 17, 20};
    cout << cutRod(price);
    return 0;
}
Java
import java.util.*;

public class GFG {
    public static int cutRod(int[] price)
    {
        int n = price.length;
        int[] dp = new int[n + 1];

        // Find maximum value for each rod length
        for (int i = 1; i <= n; i++) {

            // Try every possible first cut
            for (int j = 1; j <= i; j++) {
                dp[i] = Math.max(dp[i],
                                 price[j - 1] + dp[i - j]);
            }
        }

        return dp[n];
    }

    public static void main(String[] args)
    {
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };
        System.out.println(cutRod(price));
    }
}
Python
def cutRod(price):
    n = len(price)
    dp = [0] * (n + 1)

    # Find maximum value for each rod length
    for i in range(1, n + 1):

        # Try every possible first cut
        for j in range(1, i + 1):
            dp[i] = max(dp[i], price[j - 1] + dp[i - j])

    return dp[n]

if __name__ == "__main__":
    price = [1, 5, 8, 9, 10, 17, 17, 20]
    print(cutRod(price))
C#
using System;

public class GFG {
    public static int cutRod(int[] price)
    {
        int n = price.Length;
        int[] dp = new int[n + 1];

        // Find maximum value for each rod length
        for (int i = 1; i <= n; i++) {

            // Try every possible first cut
            for (int j = 1; j <= i; j++) {
                dp[i] = Math.Max(dp[i],
                                 price[j - 1] + dp[i - j]);
            }
        }

        return dp[n];
    }

    public static void Main()
    {
        int[] price = { 1, 5, 8, 9, 10, 17, 17, 20 };
        Console.WriteLine(cutRod(price));
    }
}
JavaScript
function cutRod(price)
{
    let n = price.length;
    let dp = new Array(n + 1).fill(0);

    // Find maximum value for each rod length
    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= i; j++) {
            dp[i]
                = Math.max(dp[i], price[j - 1] + dp[i - j]);
        }
    }

    return dp[n];
}

// Driver Code
let price = [ 1, 5, 8, 9, 10, 17, 17, 20 ];
console.log(cutRod(price));

Output
22
Comment