Maximum Product Cutting (original) (raw)

Given a rope of length n meters, cut the rope in different parts of integer lengths in a way that maximizes product of lengths of all parts. You must make at least one cut. Assume that the length of rope is more than 2 meters.

**Examples:

**Input: n = 2
**Output: 1
**Explanation: Maximum obtainable product is 1 * 1 = 1

**Input: n = 3
**Output: 6
**Explanation: You can cut rope into following ways:
1 * 1 * 1 = 1
1 * 2 = 2
2 * 1 = 2
Maximum obtainable product is 1 * 2 = 2 = 2 * 1

Table of Content

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

This problem is similar to Rod Cutting Problem. We can get the maximum product by making a cut at different positions and comparing the values obtained after a cut. We can recursively call the same function for a piece obtained after a cut.

#include using namespace std;

int maxProduct(int n) { // Base Case // Rope of length 0 or 1 // cannot be further divided if (n == 0 || n == 1) { return 0; }

// Store maximum product
int maxValue = 0;

// Try every possible cut
for (int i = 1; i < n; i++)
{
    // 1. Cut rope into two parts
    int directProduct = i * (n - i);

    // 2. Further divide remaining part
    int recursiveProduct = i * maxProduct(n - i);

    // Store maximum product
    maxValue = max(maxValue, max(directProduct, recursiveProduct));
}

return maxValue;

}

// Driver Code int main() { int n = 10; cout << "Maximum Product is " << maxProduct(n);

return 0;

}

C

#include <stdio.h>

// Utility function to return maximum int max(int a, int b) { return (a > b) ? a : b; }

int maxProduct(int n) { // Base Case // Rope of length 0 or 1 // cannot be further divided if (n == 0 || n == 1) { return 0; }

// Store maximum product
int maxValue = 0;

// Try every possible cut
for (int i = 1; i < n; i++)
{
    // 1. Cut rope into two parts
    int directProduct = i * (n - i);

    // 2. Further divide remaining part
    int recursiveProduct = i * maxProduct(n - i);

    // Store maximum product
    maxValue = max(maxValue, max(directProduct, recursiveProduct));
}

return maxValue;

}

// Driver Code int main() { int n = 10; printf("Maximum Product is %d", maxProduct(n));

return 0;

}

Java

class GFG { static int maxProduct(int n) { // Base Case // Rope of length 0 or 1 // cannot be further divided if (n == 0 || n == 1) { return 0; }

    // Store maximum product
    int maxValue = 0;

    // Try every possible cut
    for (int i = 1; i < n; i++) {
        // 1. Cut rope into two parts
        int directProduct = i * (n - i);

        // 2. Further divide remaining part
        int recursiveProduct = i * maxProduct(n - i);

        // Store maximum product
        maxValue = Math.max(
            maxValue,
            Math.max(directProduct, recursiveProduct));
    }

    return maxValue;
}

// Driver Code
public static void main(String[] args)
{
    int n = 10;
    System.out.println("Maximum Product is "
                       + maxProduct(n));
}

}

Python

def maxProduct(n):

# Base Case
# Rope of length 0 or 1
# cannot be further divided
if n == 0 or n == 1:
    return 0

# Store maximum product
maxValue = 0

# Try every possible cut
for i in range(1, n):

    # 1. Cut rope into two parts
    directProduct = i * (n - i)

    # 2. Further divide remaining part
    recursiveProduct = i * maxProduct(n - i)

    # Store maximum product
    maxValue = max(
        maxValue,
        max(directProduct, recursiveProduct)
    )

return maxValue

Driver Code

if name == "main": n = 10

print("Maximum Product is",
      maxProduct(n))

C#

using System;

class GFG { static int maxProduct(int n) { // Base Case // Rope of length 0 or 1 // cannot be further divided if (n == 0 || n == 1) { return 0; }

    // Store maximum product
    int maxValue = 0;

    // Try every possible cut
    for (int i = 1; i < n; i++) {
        // 1. Cut rope into two parts
        int directProduct = i * (n - i);

        // 2. Further divide remaining part
        int recursiveProduct = i * maxProduct(n - i);

        // Store maximum product
        maxValue = Math.Max(
            maxValue,
            Math.Max(directProduct, recursiveProduct));
    }

    return maxValue;
}

// Driver Code
static void Main()
{
    int n = 10;
    Console.WriteLine("Maximum Product is "
                      + maxProduct(n));
}

}

JavaScript

function maxProduct(n) { // Base Case // Rope of length 0 or 1 // cannot be further divided if (n === 0 || n === 1) { return 0; }

// Store maximum product
let maxValue = 0;

// Try every possible cut
for (let i = 1; i < n; i++) {
    // 1. Cut rope into two parts
    let directProduct = i * (n - i);

    // 2. Further divide remaining part
    let recursiveProduct = i * maxProduct(n - i);

    // Store maximum product
    maxValue = Math.max(
        maxValue,
        Math.max(directProduct, recursiveProduct));
}

return maxValue;

}

// Driver Code let n = 10; console.log("Maximum Product is " + maxProduct(n));

`

Output

Maximum Product is 36

Consider the following example: Recursion tree for a rope of length 5.

maxproduct_4

Explanation using recursive tree(same colored states showing overlapping sub-problems)

[Better Approach] Using Dynamic Programming - O(n ^ 2) Time and O(n) Space

The recursive solution repeatedly solves the same rope lengths again and again, such as finding the maximum product for smaller lengths multiple times. To avoid these repeated calculations, we use Dynamic Programming and store the answer for every rope length in a DP array. We build the solution from smaller lengths to larger lengths, where dp[i] stores the maximum product obtainable for a rope of length i. For every length, we try all possible cuts and use previously computed DP values to efficiently find the maximum product.

Consider the following dry run for better understanding: n = 5

Final answer = dp[5] = 6

C++ `

#include <bits/stdc++.h> using namespace std;

int maxProduct(int n) { // Base Case if (n == 0 || n == 1) { return 0; }

// DP array where
// dp[i] stores maximum product
// obtainable from rope length i
vector<int> dp(n + 1, 0);

// Build DP table from bottom up
for (int len = 2; len <= n; len++)
{
    // Store maximum product
    int maxValue = 0;

    // Try every possible cut
    for (int i = 1; i < len; i++)
    {
        // 1. Cut rope into two parts
        int directProduct = i * (len - i);

        // 2. Further divide remaining part
        int recursiveProduct = i * dp[len - i];

        // Store maximum product
        maxValue = max(maxValue, max(directProduct, recursiveProduct));
    }

    // Store answer for current length
    dp[len] = maxValue;
}

return dp[n];

}

// Driver Code int main() { int n = 10; cout << "Maximum Product is " << maxProduct(n);

return 0;

}

C

#include <stdio.h>

// Utility function to return maximum int max(int a, int b) { return (a > b) ? a : b; }

int maxProduct(int n) { // Base Case if (n == 0 || n == 1) { return 0; }

// DP array where
// dp[i] stores maximum product
// obtainable from rope length i
int dp[n + 1];

// Initialize DP array
for (int i = 0; i <= n; i++)
{
    dp[i] = 0;
}

// Build DP table from bottom up
for (int len = 2; len <= n; len++)
{
    // Store maximum product
    int maxValue = 0;

    // Try every possible cut
    for (int i = 1; i < len; i++)
    {
        // 1. Cut rope into two parts
        int directProduct = i * (len - i);

        // 2. Further divide remaining part
        int recursiveProduct = i * dp[len - i];

        // Store maximum product
        maxValue = max(maxValue, max(directProduct, recursiveProduct));
    }

    // Store answer for current length
    dp[len] = maxValue;
}

return dp[n];

}

// Driver Code int main() { int n = 10; printf("Maximum Product is %d", maxProduct(n));

return 0;

}

Java

class GFG { static int maxProduct(int n) { // Base Case if (n == 0 || n == 1) { return 0; }

    // DP array where
    // dp[i] stores maximum product
    // obtainable from rope length i
    int[] dp = new int[n + 1];

    // Build DP table from bottom up
    for (int len = 2; len <= n; len++) {
        // Store maximum product
        int maxValue = 0;

        // Try every possible cut
        for (int i = 1; i < len; i++) {
            // 1. Cut rope into two parts
            int directProduct = i * (len - i);

            // 2. Further divide remaining part
            int recursiveProduct = i * dp[len - i];

            // Store maximum product
            maxValue = Math.max(
                maxValue, Math.max(directProduct,
                                   recursiveProduct));
        }

        // Store answer for current length
        dp[len] = maxValue;
    }

    return dp[n];
}

// Driver Code
public static void main(String[] args)
{
    int n = 10;
    System.out.println("Maximum Product is "
                       + maxProduct(n));
}

}

Python

def maxProduct(n):

# Base Case
if n == 0 or n == 1:
    return 0

# DP array where
# dp[i] stores maximum product
# obtainable from rope length i
dp = [0] * (n + 1)

# Build DP table from bottom up
for length in range(2, n + 1):

    # Store maximum product
    maxValue = 0

    # Try every possible cut
    for i in range(1, length):

        # 1. Cut rope into two parts
        directProduct = i * (length - i)

        # 2. Further divide remaining part
        recursiveProduct = i * dp[length - i]

        # Store maximum product
        maxValue = max(
            maxValue,
            max(directProduct,
                recursiveProduct)
        )

    # Store answer for current length
    dp[length] = maxValue

return dp[n]

Driver Code

if name == "main": n = 10 print("Maximum Product is", maxProduct(n))

C#

using System;

class GFG { static int maxProduct(int n) { // Base Case if (n == 0 || n == 1) { return 0; }

    // DP array where
    // dp[i] stores maximum product
    // obtainable from rope length i
    int[] dp = new int[n + 1];

    // Build DP table from bottom up
    for (int len = 2; len <= n; len++) {
        // Store maximum product
        int maxValue = 0;

        // Try every possible cut
        for (int i = 1; i < len; i++) {
            // 1. Cut rope into two parts
            int directProduct = i * (len - i);

            // 2. Further divide remaining part
            int recursiveProduct = i * dp[len - i];

            // Store maximum product
            maxValue = Math.Max(
                maxValue, Math.Max(directProduct,
                                   recursiveProduct));
        }

        // Store answer for current length
        dp[len] = maxValue;
    }

    return dp[n];
}

// Driver Code
static void Main()
{
    int n = 10;
    Console.WriteLine("Maximum Product is "
                      + maxProduct(n));
}

}

JavaScript

function maxProduct(n) { // Base Case if (n === 0 || n === 1) { return 0; }

// DP array where
// dp[i] stores maximum product
// obtainable from rope length i
let dp = new Array(n + 1).fill(0);

// Build DP table from bottom up
for (let len = 2; len <= n; len++) {
    // Store maximum product
    let maxValue = 0;

    // Try every possible cut
    for (let i = 1; i < len; i++) {
        // 1. Cut rope into two parts
        let directProduct = i * (len - i);

        // 2. Further divide remaining part
        let recursiveProduct = i * dp[len - i];

        // Store maximum product
        maxValue = Math.max(
            maxValue,
            Math.max(directProduct, recursiveProduct));
    }

    // Store answer for current length
    dp[len] = maxValue;
}

return dp[n];

}

// Driver Code let n = 10; console.log("Maximum Product is " + maxProduct(n));

`

Output

Maximum Product is 36

[Optimal Approach] Using Mathematical Greedy Approach - O(n) Time and O(1) Space

Instead of trying all possible cuts using recursion or DP, this method uses an important mathematical observation: To get the maximum product, we should cut the rope into as many parts of 3 as possible.

**Why does this work?

#include using namespace std;

int maxProduct(int n) { // Base Cases // Rope of length 2 or 3 // must be cut at least once if (n == 2 || n == 3) { return n - 1; }

// Store final product
int product = 1;

// Keep cutting parts of length 3
// while remaining length is greater than 4
while (n > 4)
{
    // Multiply current product by 3
    product *= 3;

    // Reduce rope length
    n -= 3;
}

// Multiply remaining rope length
return product * n;

}

// Driver Code int main() { int n = 10; cout << "Maximum Product is " << maxProduct(n);

return 0;

}

C

#include <stdio.h>

// Function to calculate maximum product int maxProduct(int n) { // Base Cases // Rope of length 2 or 3 // must be cut at least once if (n == 2 || n == 3) { return n - 1; }

// Store final product
int product = 1;

// Keep cutting parts of length 3
// while remaining length is greater than 4
while (n > 4)
{
    // Multiply current product by 3
    product *= 3;

    // Reduce rope length
    n -= 3;
}

// Multiply remaining rope length
return product * n;

}

// Driver Code int main() { int n = 10; printf("Maximum Product is %d", maxProduct(n));

return 0;

}

Java

public class GFG {

public static int maxProduct(int n)
{
    // Base Cases
    // Rope of length 2 or 3
    // must be cut at least once
    if (n == 2 || n == 3) {
        return n - 1;
    }

    // Store final product
    int product = 1;

    // Keep cutting parts of length 3
    // while remaining length is greater than 4
    while (n > 4) {
        // Multiply current product by 3
        product *= 3;

        // Reduce rope length
        n -= 3;
    }

    // Multiply remaining rope length
    return product * n;
}

// Driver Code
public static void main(String[] args)
{
    int n = 10;
    System.out.println("Maximum Product is "
                       + maxProduct(n));
}

}

Python

def maxProduct(n): # Base Cases # Rope of length 2 or 3 # must be cut at least once if n == 2 or n == 3: return n - 1

# Store final product
product = 1

# Keep cutting parts of length 3
# while remaining length is greater than 4
while n > 4:
    # Multiply current product by 3
    product *= 3

    # Reduce rope length
    n -= 3

# Multiply remaining rope length
return product * n

Driver Code

if name == "main": n = 10 print("Maximum Product is", maxProduct(n))

C#

using System;

class GFG { static int maxProduct(int n) { // Base Cases // Rope of length 2 or 3 // must be cut at least once if (n == 2 || n == 3) { return n - 1; }

    // Store final product
    int product = 1;

    // Keep cutting parts of length 3
    // while remaining length is greater than 4
    while (n > 4) {
        // Multiply current product by 3
        product *= 3;

        // Reduce rope length
        n -= 3;
    }

    // Multiply remaining rope length
    return product * n;
}

// Driver Code
static void Main()
{
    int n = 10;
    Console.WriteLine("Maximum Product is "
                      + maxProduct(n));
}

}

JavaScript

function maxProduct(n) { // Base Cases // Rope of length 2 or 3 // must be cut at least once if (n === 2 || n === 3) { return n - 1; }

// Store final product
let product = 1;

// Keep cutting parts of length 3
// while remaining length is greater than 4
while (n > 4) {
    // Multiply current product by 3
    product *= 3;

    // Reduce rope length
    n -= 3;
}

// Multiply remaining rope length
return product * n;

}

// Driver Code let n = 10; console.log("Maximum Product is " + maxProduct(n));

`

Output

Maximum Product is 36

[Optimal Approach] Using Exponentiation - O(log n) Time and O(1) Space

In the above solution, instead of repeatedly subtracting 3 from n and multiplying the result by 3 in a loop, we observe that the number of times we can take 3 is simply n / 3. Therefore, the repeated multiplication of 3 can be represented as exponentiation 3^(n/3), which eliminates the need for iteration.

#include <bits/stdc++.h> using namespace std;

int maxProduct(int n) { // Edge case: for small values if (n == 2 || n == 3) return n - 1;

// Count how many 3s we can take
int count3 = n / 3;
int rem = n % 3;

// If remainder is 1, adjust (3 + 1 -> 2 + 2)
if (rem == 1)
{
    count3 -= 1;
    rem += 3; // becomes 4
}

// Final product
int product = 1;

// multiply all 3s
for (int i = 0; i < count3; i++)
    product *= 3;

// handle remaining part (0, 2 or 4)
if (rem == 2 || rem == 4)
    product *= rem;

return product;

}

int main() { int n = 10; cout << "Maximum Product is " << maxProduct(n); return 0; }

C

#include <stdio.h>

int maxProduct(int n) { // Edge case: for small values if (n == 2 || n == 3) return n - 1;

// Count how many 3s we can take
int count3 = n / 3;
int rem = n % 3;

// If remainder is 1, adjust (3 + 1 -> 2 + 2)
if (rem == 1)
{
    count3 -= 1;
    rem += 3; // becomes 4
}

// Final product
int product = 1;

// multiply all 3s
for (int i = 0; i < count3; i++)
    product *= 3;

// handle remaining part (0, 2 or 4)
if (rem == 2 || rem == 4)
    product *= rem;

return product;

}

int main() { int n = 10; printf("Maximum Product is %d", maxProduct(n)); return 0; }

Java

public class GFG {

static int maxProduct(int n)
{
    // Edge case: for small values
    if (n == 2 || n == 3)
        return n - 1;

    // Count how many 3s we can take
    int count3 = n / 3;
    int rem = n % 3;

    // If remainder is 1, adjust (3 + 1 -> 2 + 2)
    if (rem == 1) {
        count3 -= 1;
        rem += 3; // becomes 4
    }

    // Final product
    int product = 1;

    // multiply all 3s
    for (int i = 0; i < count3; i++)
        product *= 3;

    // handle remaining part (0, 2 or 4)
    if (rem == 2 || rem == 4)
        product *= rem;

    return product;
}

public static void main(String[] args)
{
    int n = 10;
    System.out.println("Maximum Product is "
                       + maxProduct(n));
}

}

Python

def maxProduct(n): # Edge case: for small values if n == 2 or n == 3: return n - 1

# Count how many 3s we can take
count3 = n // 3
rem = n % 3

# If remainder is 1, adjust (3 + 1 -> 2 + 2)
if rem == 1:
    count3 -= 1
    rem += 3  # becomes 4

# Final product
product = 1

# multiply all 3s
for _ in range(count3):
    product *= 3

# handle remaining part (0, 2 or 4)
if rem == 2 or rem == 4:
    product *= rem

return product

Driver Code

if name == "main": n = 10 print("Maximum Product is", maxProduct(n))

C#

using System;

class GFG { static int maxProduct(int n) { // Edge case: for small values if (n == 2 || n == 3) return n - 1;

    // Count how many 3s we can take
    int count3 = n / 3;
    int rem = n % 3;

    // If remainder is 1, adjust (3 + 1 -> 2 + 2)
    if (rem == 1) {
        count3 -= 1;
        rem += 3; // becomes 4
    }

    // Final product
    int product = 1;

    // multiply all 3s
    for (int i = 0; i < count3; i++)
        product *= 3;

    // handle remaining part (0, 2 or 4)
    if (rem == 2 || rem == 4)
        product *= rem;

    return product;
}

static void Main()
{
    int n = 10;
    Console.WriteLine("Maximum Product is "
                      + maxProduct(n));
}

}

JavaScript

function maxProduct(n) { // Edge case: for small values if (n === 2 || n === 3) return n - 1;

// Count how many 3s we can take
let count3 = Math.floor(n / 3);
let rem = n % 3;

// If remainder is 1, adjust (3 + 1 -> 2 + 2)
if (rem === 1) {
    count3 -= 1;
    rem += 3; // becomes 4
}

// Final product
let product = 1;

// multiply all 3s
for (let i = 0; i < count3; i++)
    product *= 3;

// handle remaining part (0, 2 or 4)
if (rem === 2 || rem === 4)
    product *= rem;

return product;

}

// Driver Code let n = 10; console.log("Maximum Product is " + maxProduct(n));

`

Output

Maximum Product is 36