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.
- We try cutting the rope at every possible position from 1 to n - 1.
- For every cut, we calculate two possibilities: directly multiply the two rope parts, or further divide the remaining rope recursively.
- The recursive function keeps exploring all possible cuts to find the maximum product.
- At every step, we store the maximum product obtained so far in maxValue.
- Finally, the function returns the maximum product possible after cutting the rope.
#include <iostream>
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;
}
#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;
}
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));
}
}
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))
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));
}
}
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.

[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
- For len = 2 :
i = 1 --> directProduct = 1 * 1 = 1, recursiveProduct = 1 * dp[1] = 0
dp[2] = max(1, 0) = 1 - For len = 3 :
i = 1 --> directProduct = 1 * 2 = 2, recursiveProduct = 1 * dp[2] = 1 ---> max(2, 1) = 2
i = 2 --> directProduct = 2 * 1 = 2, recursiveProduct = 2 * dp[1] = 0 ---> max(2, 0) = 2
dp[3] = max(2, 2) = 2 - For len = 4 :
i = 1 --> directProduct = 1 * 3 = 3, recursiveProduct = 1 * dp[3] = 2 ---> max(3, 2) = 3
i = 2 --> directProduct = 2 * 2 = 4, recursiveProduct = 2 * dp[2] = 2 ---> max(4, 2) = 4
i = 3 --> directProduct = 3 * 1 = 3, recursiveProduct = 3 * dp[1] = 0 ---> max(3, 0) = 3
dp[4] = max(3, 4, 3) = 4 - For len = 5 :
i = 1 --> directProduct = 1 * 4 = 4, recursiveProduct = 1 * dp[4] = 4 ---> max(4, 4) = 4
i = 2 --> directProduct = 2 * 3 = 6, recursiveProduct = 2 * dp[3] = 4 ---> max(6, 4) = 6
i = 3 --> directProduct = 3 * 2 = 6, recursiveProduct = 3 * dp[2] = 3 ---> max(6, 3) = 6
i = 4 --> directProduct = 4 * 1 = 4, recursiveProduct = 4 * dp[1] = 0 ---> max(4, 0) = 4
dp[5] = max(4, 6, 6, 4) = 6
Final answer = dp[5] = 6
#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;
}
#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;
}
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));
}
}
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))
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));
}
}
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.
- If we see some examples of this problems, we can easily observe following pattern.
- The maximum product can be obtained be repeatedly cutting parts of size 3 while size is greater than 4, keeping the last part as size of 2 or 3 or 4.
- For n = 10, the maximum product is obtained by 3, 3, 4.
- For n = 11, the maximum product is obtained by 3, 3, 3, 2.
Why does this work?
- If we cut of length x into
a + b, the product becomes a x b. We should cut only if a×b > x otherwise cutting reduces the product. - If we take values of x less than 4, we can notice, we never need to cut. For example 3 = 2 + 1, but 2 x 1 < 3
- For 4, we get max same values 2x2 = 4.
- Let us now consider x >= 5, let us consider two choices make a cut of length 2 and 3 and compare the two choices 2(x-2) and 3(x-3). If we compute 3(x - 3) - 2(x-2), get x - 5 which is greater than or equal to 0 (never negative). So cutting into a piece of 3 is always better.
- Now the question arises about larger cuts. We can show that any length larger than 5 needs to be cut for more product. Why? because 3(x - 3) > x for x >= 4.5.
#include <iostream>
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;
}
#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;
}
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));
}
}
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))
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));
}
}
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.
- If n is 2 or 3, directly return n - 1 as it is the best possible split.
- Compute how many full 3s can be taken from n using integer division:
count3 = n / 3, and find the remainder: rem = n % 3. - If rem is 0 --> only 3s are used
- If rem is 2 --> multiply final result by 2
- If rem is 1 --> adjust by converting one 3 + 1 into 2 + 2 for optimal product
- Multiply the result by 3 repeatedly count3 times to account for all 3-partitions.
- Multiply the final result by rem (if it is 2 or 4), and return the product as the answer.
#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;
}
#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;
}
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));
}
}
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))
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));
}
}
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