Rod Cutting (original) (raw)

Given a rod of length n and an array price[]. price[i] denotes the price of a piece of length i. Determine the maximum amount obtained by cutting the rod into pieces and selling the pieces.

**Note: price[0] is always 0.

**Input: price[] = [0, 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[] = [0, 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[] = [0, 3]
**Output : 3
**Explanation: There is only 1 way to pick a piece of length 1.

Table of Content

Using Recursion - O(2^n) Time and O(n) Space

#include #include #include

using namespace std;

int cutRodRecur(int i, vector& price) {

// Base case
if (i == 0) return 0;

int ans = 0;

// Find maximum value for rod of length i
// by considering each cut of length j 
// such that j <= i
for (int j = 1; j <= i; j++) {
    ans = max(ans, price[j] + cutRodRecur(i - j, price));
}

return ans;

}

int cutRod(vector& price) { int n = price.size() - 1;

return cutRodRecur(n, price);

}

int main() { vector price = {0, 1, 5, 8, 9, 10, 17, 17, 20}; cout << cutRod(price); return 0; }

Java

class GFG {

static int cutRodRecur(int i, int[] price) {
    
    // Base case
    if (i == 0) return 0;
    
    int ans = 0;

    // Find maximum value for rod of length i
    // by considering each cut of length j 
    // such that j <= i
    for (int j = 1; j <= i; j++) {
        ans = Math.max(ans, price[j] + cutRodRecur(i - j, price));
    }

    return ans;
}

static int cutRod(int[] price) {
    int n = price.length-1;

    return cutRodRecur(n, price);
}

public static void main(String[] args) {
    int[] price = {0, 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

ans = 0

# Find maximum value for rod of length i
# by considering each cut of length j 
# such that j <= i
for j in range(1, i + 1):
    ans = max(ans, price[j] + cutRodRecur(i - j, price))

return ans

def cutRod(price): n = len(price) - 1

return cutRodRecur(n, price)

if name == "main": price = [1, 5, 8, 9, 10, 17, 17, 20] print(cutRod(price))

C#

using System;

class GFG {

static int cutRodRecur(int i, int[] price) {

    // Base case
    if (i == 0) return 0;

    int ans = 0;

    // Find maximum value for rod of length i
    // by considering each cut of length j 
    // such that j <= i
    for (int j = 1; j <= i; j++) {
        ans = Math.Max(ans, price[j] + cutRodRecur(i - j, price));
    }

    return ans;
}

static int cutRod(int[] price) {
    int n = price.Length - 1;

    return cutRodRecur(n, price);
}

public static void Main(string[] args) {
    int[] price = {0, 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 ans = 0;

// Find maximum value for rod of length i
// by considering each cut of length j 
// such that j <= i
for (let j = 1; j <= i; j++) {
    ans = Math.max(ans, price[j] + cutRodRecur(i - j, price));
}

return ans;

}

function cutRod(price) { const n = price.length-1;

return cutRodRecur(n, price);

}

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

`

Using the idea of Unbounded Knapsack - O(n^2) time and O(n^2) space

#include #include #include using namespace std;

// i - length of current rod // j - remaining rod length int cutRodRecur(int i, int j, const vector& price, vector<vector>& dp) {

// base case 
if (i == 0 || j == 0) return 0;

// If value is stored in dp array
if (dp[i][j] != -1) return dp[i][j];

// There are two options:
// 1. Break it into (i) and (i-j) rods and 
// take value of ith rod.
int take = 0;
if (i <= j) {
    take = price[i] + cutRodRecur(i, j - i, price, dp);
}

// 2. Skip i'th length rod.
int noTake = cutRodRecur(i - 1, j, price, dp);

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

}

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

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

}

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

Java

import java.util.Arrays;

class GFG {

// i - length of current rod
// j - remaining rod length
static int cutRodRecur(int i, int j, 
                       int[] price, int[][] dp) {

    // base case 
    if (i == 0 || j == 0) return 0;

    // If value is stored in dp array
    if (dp[i][j] != -1) return dp[i][j];

    // There are two options:
    // 1. Break it into (i) and (i-j) rods and 
    // take value of ith rod.
    int take = 0;
    if (i <= j) {
        take = price[i] + cutRodRecur(i, j - i, price, dp);
    }

    // 2. Skip i'th length rod.
    int noTake = cutRodRecur(i - 1, j, price, dp);

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

static int cutRod(int[] price) {
    int n = price.length-1;
    int[][] dp = new int[n + 1][n + 1];
    
    // filling the dp array with invalid values
    for (int[] row : dp) {
        Arrays.fill(row, -1);
    }

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

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

}

Python

i - length of current rod

j - remaining rod length

def cutRodRecur(i, j, price, dp):

# base case 
if i == 0 or j == 0:
    return 0

# If value is stored in dp array
if dp[i][j] != -1:
    return dp[i][j]

# There are two options:
# 1. Break it into (i) and (i-j) rods and 
# take value of ith rod.
take = 0
if i <= j:
    take = price[i] + cutRodRecur(i, j - i, price, dp)

# 2. Skip i'th length rod.
noTake = cutRodRecur(i - 1, j, price, dp)

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

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

return cutRodRecur(n, n, price, dp)

if name == "main": price = [0, 1, 5, 8, 9, 10, 17, 17, 20] print(cutRod(price))

C#

using System;

class GFG {

// i - length of current rod
// j - remaining rod length
static int cutRodRecur(int i, int j, int[] price, int[][] dp) {

    // base case 
    if (i == 0 || j == 0) return 0;

    // If value is stored in dp array
    if (dp[i][j] != -1) return dp[i][j];

    // There are two options:
    // 1. Break it into (i) and (i-j) rods and 
    // take value of ith rod.
    int take = 0;
    if (i <= j) {
        take = price[i] + cutRodRecur(i, j - i, price, dp);
    }

    // 2. Skip i'th length rod.
    int noTake = cutRodRecur(i - 1, j, price, dp);

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

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

    for (int k = 0; k <= n; k++) {
        dp[k] = new int[n + 1];
        for (int t = 0; t <= n; t++)
            dp[k][t] = -1;
    }

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

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

}

JavaScript

// i - length of current rod // j - remaining rod length function cutRodRecur(i, j, price, dp) {

// base case 
if (i === 0 || j === 0) return 0;

// If value is stored in dp array
if (dp[i][j] !== -1) return dp[i][j];

// There are two options:
// 1. Break it into (i) and (i-j) rods and 
// take value of ith rod.
let take = 0;
if (i <= j) {
    take = price[i] + cutRodRecur(i, j - i, price, dp);
}

// 2. Skip i'th length rod.
let noTake = cutRodRecur(i - 1, j, price, dp);

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

}

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

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

}

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

`

Using Top-Down DP (Memoization) - O(n^2) Time and O(n) Space

#include #include #include #include

using namespace std;

int cutRodRecur(int i, vector& price, vector& dp) {

// Base case
if (i == 0) return 0;

// If answer for this dp 
// state is already calculated
if (dp[i] != -1) return dp[i];

int ans = 0;

// Find maximum value for each cut.
// Take value of rod of length j, and 
// recursively find value of rod of 
// length (i-j).
for (int j = 1; j <= i; j++) {
    ans = max(ans, price[j] + cutRodRecur(i - j, price, dp));
}

return dp[i] = ans;

}

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

return cutRodRecur(n, price, dp);

}

int main() { vector price = {0, 1, 5, 8, 9, 10, 17, 17, 20}; cout << cutRod(price); return 0; }

Java

import java.util.Arrays;

class GFG {

static int cutRodRecur(int i, int[] price, int[] dp) {
    
    // Base case
    if (i == 0) return 0;
    
    // If answer for this dp 
    // state is already calculated
    if (dp[i] != -1) return dp[i];
    
    int ans = 0;

    // Find maximum value for each cut.
    // Take value of rod of length j, and 
    // recursively find value of rod of 
    // length (i-j).
    for (int j = 1; j <= i; j++) {
        ans = Math.max(ans, price[j] + cutRodRecur(i - j, price, dp));
    }

    return dp[i] = ans;
}

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

public static void main(String[] args) {
    int[] price = {0, 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

# If answer for this dp 
# state is already calculated
if dp[i] != -1:
    return dp[i]

ans = 0

# Find maximum value for each cut.
# Take value of rod of length j, and 
# recursively find value of rod of 
# length (i-j).
for j in range(1, i + 1):
    ans = max(ans, price[j] + cutRodRecur(i - j, price, dp))

dp[i] = ans
return ans

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

if name == "main": price = [0, 1, 5, 8, 9, 10, 17, 17, 20] print(cutRod(price))

C#

using System;

class GFG {

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

    // If answer for this dp 
    // state is already calculated
    if (dp[i] != -1) return dp[i];

    int ans = 0;

    // Find maximum value for each cut.
    // Take value of rod of length j, and 
    // recursively find value of rod of 
    // length (i-j).
    for (int j = 1; j <= i; j++) {
        ans = Math.Max(ans, price[j] + cutRodRecur(i - j, price, dp));
    }

    return dp[i] = ans;
}

static int cutRod(int[] price) {
    int n = price.Length - 1;
    int[] dp = new int[n + 1];
    for (int k = 0; k <= n; k++) dp[k] = -1;

    return cutRodRecur(n, price, dp);
}

public static void Main(string[] args) {
    int[] price = {0, 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;

// If answer for this dp 
// state is already calculated
if (dp[i] !== -1) return dp[i];

let ans = 0;

// Find maximum value for each cut.
// Take value of rod of length j, and 
// recursively find value of rod of 
// length (i-j).
for (let j = 1; j <= i; j++) {
    ans = Math.max(ans, price[j] + cutRodRecur(i - j, price, dp));
}

return dp[i] = ans;

}

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

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

`

Using Bottom-Up DP (Tabulation) - O(n^2) Time and O(n) Space

#include #include #include

using namespace std;

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

// Find maximum value for all 
// rod of length i.
for (int i = 1; i <= n; i++) {
    
    // dividing rod of length i 
    // into smaller piecess recursively
    for (int j = 1; j <= i; j++) {
        dp[i] = max(dp[i], price[j] + dp[i - j]);
    }
}

return dp[n];

}

int main() { vector price = {0, 1, 5, 8, 9, 10, 17, 17, 20}; cout << cutRod(price); return 0; }

Java

class GFG {

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

    // Find maximum value for all 
    // rod of length i.
    for (int i = 1; i <= n; i++) {
        
        // dividing rod of length i 
        // into smaller piecess recursively
        for (int j = 1; j <= i; j++) {
            dp[i] = Math.max(dp[i], price[j] + dp[i - j]);
        }
    }

    return dp[n];
}

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

}

Python

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

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

    # dividing rod of length i 
    # into smaller piecess recursively
    for j in range(1, i + 1):
        dp[i] = max(dp[i], price[j] + dp[i - j])

return dp[n]

if name == "main": price = [0, 1, 5, 8, 9, 10, 17, 17, 20] print(cutRod(price))

C#

using System;

class GFG {

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

    // Find maximum value for all 
    // rod of length i.
    for (int i = 1; i <= n; i++) {
        
        // dividing rod of length i 
        // into smaller piecess recursively
        for (int j = 1; j <= i; j++) {
            dp[i] = Math.Max(dp[i], price[j] + dp[i - j]);
        }
    }

    return dp[n];
}

public static void Main(string[] args) {
    int[] price = {0, 1, 5, 8, 9, 10, 17, 17, 20};
    Console.WriteLine(cutRod(price));
}

}

JavaScript

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

// Find maximum value for all 
// rod of length i.
for (let i = 1; i <= n; i++) {

    // dividing rod of length i 
    // into smaller piecess recursively
    for (let j = 1; j <= i; j++) {
        dp[i] = Math.max(dp[i], price[j] + dp[i - j]);
    }
}

return dp[n];

}

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

`