Maximize the number of segments of length x, y and z (original) (raw)
Given a **rod of **length n, the task is to **cut the rod in such a way that the **total number of segments of **length x, y, and z is **maximized. The segments can only be of length x, y, and z.
Note: If **no segment can be cut then return 0.
**Examples:
**Input: n = 4, x = 2, y = 1, z = 1
**Output: 4
**Explanation: Total length is 4, and the cut lengths are 2, 1 and 1. We can make maximum 4 segments each of length 1.**Input: n = 5, x = 5, y = 3, z = 2
**Output: 2
**Explanation: Here total length is 5, and the cut lengths are 5, 3 and 2. We can make two segments of lengths 3 and 2.**Input: n = 7, x = 8, y = 9, z = 10
**Output: 0
**Explanation: Here the total length is 7, and the cut lengths are 8, 9, and 10. We cannot cut the segment into lengths that fully utilize the segment, so the output is 0.
Table of Content
- Using Recursion - O(3^n) Time and O(n) Space
- Using Top-Down DP (Memoization) - O(n) Time and O(n) Space
- Using Bottom-Up DP (Tabulation) - O(n) Time and O(n) Space
Using Recursion - O(3^n) Time and O(n) Space
For the recursive approach, the function explores all possible ways to cut the rod into segments of given lengths. At each step, it considers three options:
- Reduce the **length by the first segment length (x).
- Reduce the **length by the second segment length (y).
- Reduce the **length by the third segment length (z).
The **recurrence relation for the problem is as follows:
**if n < 0
**maxCutHelper(n, x, y, z) = -1,**else
**maxCutHelper(n, x, y, z) = 1 + max(maxCutHelper(n - x, x, y, z), maxCutHelper(n - y, x, y, z), maxCutHelper(n - z, x, y, z))**Base Cases:
- If the rod length is **zero (n = 0), return 0 (no more cuts can be made).
- If the rod length **becomes negative (n < 0), **return -1 (invalid result).
C++ `
// C++ implementation to find max cut segments // using Recursion #include <bits/stdc++.h> using namespace std;
// Helper function to maximize the number // of cuts using recursion int maxCutHelper(int n, int x, int y, int z) {
// Base case: If the length is zero,
// return zero cuts
if (n == 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
int cut1 = maxCutHelper(n - x, x, y, z);
int cut2 = maxCutHelper(n - y, x, y, z);
int cut3 = maxCutHelper(n - z, x, y, z);
// Get the maximum number of cuts among
// the 3 options
int maxCut = max(cut1, max(cut2, cut3));
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut == -1) {
return -1;
}
return maxCut + 1;}
// Main function to start the cutting process int maximizeTheCuts(int n, int x, int y, int z) {
int res = maxCutHelper(n, x, y, z);
// No valid cuts found
if(res == -1) return 0;
return res;}
int main() {
int n = 11;
int x = 2, y = 3, z = 5;
cout << maximizeTheCuts(n, x, y, z);
return 0;}
Java
// Java implementation to find max cut segments // using Recursion class GfG {
// Helper function to maximize the number
// of cuts using recursion
static int maxCutHelper(int n, int x, int y, int z) {
// Base case: If the length is zero,
// return zero cuts
if (n == 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
int cut1 = maxCutHelper(n - x, x, y, z);
int cut2 = maxCutHelper(n - y, x, y, z);
int cut3 = maxCutHelper(n - z, x, y, z);
// Get the maximum number of cuts among
// the 3 options
int maxCut = Math.max(cut1, Math.max(cut2, cut3));
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut == -1) {
return -1;
}
return maxCut + 1;
}
// Main function to start the cutting process
static int maximizeTheCuts(int n, int x, int y, int z) {
int res = maxCutHelper(n, x, y, z);
// No valid cuts found
if (res == -1) return 0;
return res;
}
public static void main(String[] args) {
int n = 11;
int x = 2, y = 3, z = 5;
System.out.println(maximizeTheCuts(n, x, y, z));
}}
Python
Python implementation to find max cut segments
using Recursion
Helper function to maximize the number
of cuts using recursion
def maxCutHelper(n, x, y, z):
# Base case: If the length is zero,
# return zero cuts
if n == 0:
return 0
# Base case: If the length becomes negative,
# return an invalid result
if n < 0:
return -1
# Recursive step: Try all three segment
# lengths and choose the maximum result
cut1 = maxCutHelper(n - x, x, y, z)
cut2 = maxCutHelper(n - y, x, y, z)
cut3 = maxCutHelper(n - z, x, y, z)
# Get the maximum number of cuts among
# the 3 options
maxCut = max(cut1, cut2, cut3)
# If no valid cut found, return negative
# value indicating no valid cuts
if maxCut == -1:
return -1
return maxCut + 1Main function to start the cutting process
def maximizeTheCuts(n, x, y, z):
res = maxCutHelper(n, x, y, z)
# No valid cuts found
if res == -1:
return 0
return resif name == "main":
n = 11
x = 2
y = 3
z = 5
print(maximizeTheCuts(n, x, y, z))C#
// C# implementation to find max cut segments // using Recursion using System;
class GfG {
// Helper function to maximize the number
// of cuts using recursion
static int maxCutHelper(int n, int x, int y, int z) {
// Base case: If the length is zero,
// return zero cuts
if (n == 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
int cut1 = maxCutHelper(n - x, x, y, z);
int cut2 = maxCutHelper(n - y, x, y, z);
int cut3 = maxCutHelper(n - z, x, y, z);
// Get the maximum number of cuts among
// the 3 options
int maxCut = Math.Max(cut1, Math.Max(cut2, cut3));
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut == -1) {
return -1;
}
return maxCut + 1;
}
// Main function to start the cutting process
static int maximizeTheCuts(int n, int x, int y, int z) {
int res = maxCutHelper(n, x, y, z);
// No valid cuts found
if (res == -1) return 0;
return res;
}
static void Main(string[] args) {
int n = 11;
int x = 2, y = 3, z = 5;
Console.WriteLine(maximizeTheCuts(n, x, y, z));
}}
JavaScript
// JavaScript implementation to find max cut segments // using Recursion
// Helper function to maximize the number // of cuts using recursion function maxCutHelper(n, x, y, z) {
// Base case: If the length is zero,
// return zero cuts
if (n === 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
let cut1 = maxCutHelper(n - x, x, y, z);
let cut2 = maxCutHelper(n - y, x, y, z);
let cut3 = maxCutHelper(n - z, x, y, z);
// Get the maximum number of cuts among
// the 3 options
let maxCut = Math.max(cut1, cut2, cut3);
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut === -1) {
return -1;
}
return maxCut + 1;}
// Main function to start the cutting process function maximizeTheCuts(n, x, y, z) {
let res = maxCutHelper(n, x, y, z);
// No valid cuts found
if (res === -1) return 0;
return res;}
let n = 11; let x = 2; let y = 3; let z = 5;
console.log(maximizeTheCuts(n, x, y, z));
`
Using Top-Down DP (Memoization****) -** O(n) **Time and O(n) Space
The recursive approach is optimized using **memoization, storing previously computed results in a **memo array to avoid redundant computations. The two key properties of dynamic programming are utilized:
**1. Optimal Substructure: The solution for maximizing cuts can be derived from smaller subproblems:
- If the **rod length n is **zero, the number of cuts is zero.
- If the rod length becomes **negative, the result is invalid (-1).
- Otherwise, for each segment length (x, y, z), the solution is the **maximum result of reducing the rod by that segment length and **recursively solving the subproblem.
**2. Overlapping Subproblems: The function repeatedly computes results for the **same rod length (n) with the same segment lengths. Using a **memoization array memo, where memo[n] stores the result for rod length n, avoids redundant calculations.
- Initialize a **memoization array memo of **size n + 1 with -1.
- In the recursive function, check if the result for the current rod length (n) is already computed (memo[n] != -1). If so, **return the stored result.
- Otherwise, **compute the result using the recurrence relation, and **store it in memo[n]. C++ `
// C++ implementation to find max cut segments // using Recursion and Memoization #include <bits/stdc++.h> using namespace std;
// Helper function to maximize the number // of cuts using recursion and memoization int maxCutHelper(int n, int x, int y, int z, vector& memo) {
// Base case: If the length is zero,
// return zero cuts
if (n == 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// If the result is already computed,
// return it from the memo array
if (memo[n] != -1) {
return memo[n];
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
int cut1 = maxCutHelper(n - x, x, y, z, memo);
int cut2 = maxCutHelper(n - y, x, y, z, memo);
int cut3 = maxCutHelper(n - z, x, y, z, memo);
// Get the maximum number of cuts among
// the 3 options
int maxCut = max(cut1, max(cut2, cut3));
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut == -1) {
return memo[n] = -1;
}
return memo[n] = maxCut + 1;}
// Main function to start the cutting process int maximizeTheCuts(int n, int x, int y, int z) {
// Create memoization array initialized to -1
vector<int> memo(n + 1, -1);
int res = maxCutHelper(n, x, y, z, memo);
// No valid cuts found
if(res == -1) return 0;
return res;}
int main() {
int n = 11;
int x = 2, y = 3, z = 5;
cout << maximizeTheCuts(n, x, y, z);
return 0;}
Java
// Java implementation to find max cut segments // using Recursion and Memoization class GfG {
// Helper function to maximize the number
// of cuts using recursion and memoization
static int maxCutHelper(int n, int x, int y,
int z, int[] memo) {
// Base case: If the length is zero,
// return zero cuts
if (n == 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// If the result is already computed,
// return it from the memo array
if (memo[n] != -1) {
return memo[n];
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
int cut1 = maxCutHelper(n - x, x, y, z, memo);
int cut2 = maxCutHelper(n - y, x, y, z, memo);
int cut3 = maxCutHelper(n - z, x, y, z, memo);
// Get the maximum number of cuts among
// the 3 options
int maxCut = Math.max(cut1, Math.max(cut2, cut3));
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut == -1) {
return memo[n] = -1;
}
return memo[n] = maxCut + 1;
}
// Main function to start the cutting process
static int maximizeTheCuts(int n, int x, int y, int z) {
// Create memoization array initialized to -1
int[] memo = new int[n + 1];
java.util.Arrays.fill(memo, -1);
int res = maxCutHelper(n, x, y, z, memo);
// No valid cuts found
if (res == -1) return 0;
return res;
}
public static void main(String[] args) {
int n = 11;
int x = 2, y = 3, z = 5;
System.out.println(maximizeTheCuts(n, x, y, z));
}}
Python
Python implementation to find max cut segments
using Recursion and Memoization
Helper function to maximize the number
of cuts using recursion and memoization
def maxCutHelper(n, x, y, z, memo):
# Base case: If the length is zero,
# return zero cuts
if n == 0:
return 0
# Base case: If the length becomes negative,
# return an invalid result
if n < 0:
return -1
# If the result is already computed,
# return it from the memo dictionary
if n in memo:
return memo[n]
# Recursive step: Try all three segment
# lengths and choose the maximum result
cut1 = maxCutHelper(n - x, x, y, z, memo)
cut2 = maxCutHelper(n - y, x, y, z, memo)
cut3 = maxCutHelper(n - z, x, y, z, memo)
# Get the maximum number of cuts among
# the 3 options
maxCut = max(cut1, cut2, cut3)
# If no valid cut found, return negative
# value indicating no valid cuts
if maxCut == -1:
memo[n] = -1
return -1
memo[n] = maxCut + 1
return memo[n]Main function to start the cutting process
def maximizeTheCuts(n, x, y, z):
# Create a memoization dictionary
memo = {}
res = maxCutHelper(n, x, y, z, memo)
# No valid cuts found
if res == -1:
return 0
return resif name == "main":
n = 11
x = 2
y = 3
z = 5
print(maximizeTheCuts(n, x, y, z))C#
// C# implementation to find max cut segments // using Recursion and Memoization using System; using System.Collections.Generic;
class GfG {
// Helper function to maximize the number
// of cuts using recursion and memoization
static int maxCutHelper(int n, int x, int y,
int z, Dictionary<int, int> memo) {
// Base case: If the length is zero,
// return zero cuts
if (n == 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// If the result is already computed,
// return it from the memo dictionary
if (memo.ContainsKey(n)) {
return memo[n];
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
int cut1 = maxCutHelper(n - x, x, y, z, memo);
int cut2 = maxCutHelper(n - y, x, y, z, memo);
int cut3 = maxCutHelper(n - z, x, y, z, memo);
// Get the maximum number of cuts among
// the 3 options
int maxCut = Math.Max(cut1, Math.Max(cut2, cut3));
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut == -1) {
memo[n] = -1;
return -1;
}
memo[n] = maxCut + 1;
return memo[n];
}
// Main function to start the cutting process
static int maximizeTheCuts(int n, int x, int y, int z) {
// Create a memoization dictionary
var memo = new Dictionary<int, int>();
int res = maxCutHelper(n, x, y, z, memo);
// No valid cuts found
if (res == -1) return 0;
return res;
}
static void Main(string[] args) {
int n = 11;
int x = 2, y = 3, z = 5;
Console.WriteLine(maximizeTheCuts(n, x, y, z));
}}
JavaScript
// JavaScript implementation to find max cut segments // using Recursion and Memoization
// Helper function to maximize the number // of cuts using recursion and memoization function maxCutHelper(n, x, y, z, memo) {
// Base case: If the length is zero,
// return zero cuts
if (n === 0) {
return 0;
}
// Base case: If the length becomes negative,
// return an invalid result
if (n < 0) {
return -1;
}
// If the result is already computed,
// return it from the memo object
if (n in memo) {
return memo[n];
}
// Recursive step: Try all three segment
// lengths and choose the maximum result
let cut1 = maxCutHelper(n - x, x, y, z, memo);
let cut2 = maxCutHelper(n - y, x, y, z, memo);
let cut3 = maxCutHelper(n - z, x, y, z, memo);
// Get the maximum number of cuts among
// the 3 options
let maxCut = Math.max(cut1, cut2, cut3);
// If no valid cut found, return negative
// value indicating no valid cuts
if (maxCut === -1) {
memo[n] = -1;
return -1;
}
memo[n] = maxCut + 1;
return memo[n];}
// Main function to start the cutting process function maximizeTheCuts(n, x, y, z) {
// Create a memoization object
let memo = {};
let res = maxCutHelper(n, x, y, z, memo);
// No valid cuts found
if (res === -1) return 0;
return res;}
let n = 11; let x = 2; let y = 3; let z = 5;
console.log(maximizeTheCuts(n, x, y, z));
`
Using Bottom-Up DP (Tabulation) -O(n) **Time and O(n) Space
The approach is similar to the **previous one, but instead of breaking down the problem recursively, we iteratively build up the solution by calculating in a bottom-up manner. So, we will **create a 1D array dp of size (n + 1) of type integer. The state **dp[i] will store the **maximum number of cuts possible for a rod of length i.
The dynamic programming relation is as follows:
- If the current rod length i is less than the segment length x: dp[i] = dp[i]
- Otherwise, we update **dp[i] as: dp[i] = max(dp[i], dp[i - k] + 1), where **k can be x, y, or z.
This means that if the **current rod length is **smaller than the segment length, no cut is **possible for this length, and we keep the **previous value. Otherwise, we check if **adding a segment of length k results in a **greater number of cuts and update the value of **dp[i] accordingly. Finally, if **no valid cuts are possible for the rod of length n, we **return 0. Otherwise, the value at **dp[n] will give the maximum number of cuts.
C++ `
// C++ implementation to find max cut segments // using Tabulation #include <bits/stdc++.h> using namespace std;
// Main function to start the cutting process int maximizeTheCuts(int n, int x, int y, int z) {
// Create a table to store results of subproblems
vector<int> dp(n + 1, 0);
for (int i = 1; i <= n; ++i) {
// Check if the current length is at least x
// If so, check if the previous result
// (dp[i - x]) is valid (not -1)
// Update dp[i] by considering this cut
if (i >= x && dp[i - x] != -1) {
dp[i] = max(dp[i], dp[i - x] + 1);
}
// Similarly, check for the other two possible
// cuts (y and z)
if (i >= y && dp[i - y] != -1) {
dp[i] = max(dp[i], dp[i - y] + 1);
}
if (i >= z && dp[i - z] != -1) {
dp[i] = max(dp[i], dp[i - z] + 1);
}
// If no valid cut was found for length i,
if (dp[i] == 0) {
dp[i] = -1;
}
}
// If no valid cuts are found for the full length n,
// return 0
if (dp[n] == -1) {
return 0;
}
// Return the maximum number of cuts for the rod
// of length n
return dp[n];}
int main() {
int n = 11;
int x = 2, y = 3, z = 5;
cout << maximizeTheCuts(n, x, y, z);
return 0;}
Java
// Java implementation to find max cut segments // using Tabulation class GfG {
// Main function to start the cutting process
static int maximizeTheCuts(int n, int x, int y, int z) {
// Create a table to store results of subproblems
int[] dp = new int[n + 1];
// Initialize the dp array with -1 for all lengths
// greater than 0
for (int i = 1; i <= n; ++i) {
dp[i] = -1;
}
for (int i = 1; i <= n; ++i) {
// Check if the current length is at least x
// If so, check if the previous result
// (dp[i - x]) is valid (not -1)
// Update dp[i] by considering this cut
if (i >= x && dp[i - x] != -1) {
dp[i] = Math.max(dp[i], dp[i - x] + 1);
}
// Similarly, check for the other two possible
// cuts (y and z)
if (i >= y && dp[i - y] != -1) {
dp[i] = Math.max(dp[i], dp[i - y] + 1);
}
if (i >= z && dp[i - z] != -1) {
dp[i] = Math.max(dp[i], dp[i - z] + 1);
}
// If no valid cut was found for length i,
if (dp[i] == 0) {
dp[i] = -1;
}
}
// If no valid cuts are found for the full
// length n, return 0
if (dp[n] == -1) {
return 0;
}
// Return the maximum number of cuts for
// the rod of length n
return dp[n];
}
public static void main(String[] args) {
int n = 11;
int x = 2, y = 3, z = 5;
System.out.println(maximizeTheCuts(n, x, y, z));
}}
Python
Python implementation to find max cut segments
using Tabulation
Main function to start the cutting process
def maximizeTheCuts(n, x, y, z):
# Create a table to store results of subproblems
dp = [0] * (n + 1)
for i in range(1, n + 1):
# Check if the current length is at least x
# If so, check if the previous result
# (dp[i - x]) is valid (not -1)
# Update dp[i] by considering this cut
if i >= x and dp[i - x] != -1:
dp[i] = max(dp[i], dp[i - x] + 1)
# Similarly, check for the other two possible
# cuts (y and z)
if i >= y and dp[i - y] != -1:
dp[i] = max(dp[i], dp[i - y] + 1)
if i >= z and dp[i - z] != -1:
dp[i] = max(dp[i], dp[i - z] + 1)
# If no valid cut was found for length i,
if dp[i] == 0:
dp[i] = -1
# If no valid cuts are found for the full
# length n, return 0
if dp[n] == -1:
return 0
# Return the maximum number of cuts for
# the rod of length n
return dp[n]if name == "main":
n = 11
x = 2
y = 3
z = 5
print(maximizeTheCuts(n, x, y, z))C#
// C# implementation to find max cut segments // using Tabulation using System;
class GfG {
// Main function to start the cutting process
static int maximizeTheCuts(int n, int x,
int y, int z) {
// Create a table to store results of subproblems
int[] dp = new int[n + 1];
// Initialize the dp array with -1 for all
// lengths greater than 0
for (int i = 1; i <= n; ++i) {
dp[i] = -1;
}
for (int i = 1; i <= n; ++i) {
// Check if the current length is at least x
// If so, check if the previous result
// (dp[i - x]) is valid (not -1)
// Update dp[i] by considering this cut
if (i >= x && dp[i - x] != -1) {
dp[i] = Math.Max(dp[i], dp[i - x] + 1);
}
// Similarly, check for the other two possible
// cuts (y and z)
if (i >= y && dp[i - y] != -1) {
dp[i] = Math.Max(dp[i], dp[i - y] + 1);
}
if (i >= z && dp[i - z] != -1) {
dp[i] = Math.Max(dp[i], dp[i - z] + 1);
}
// If no valid cut was found for length i,
if (dp[i] == 0) {
dp[i] = -1;
}
}
// If no valid cuts are found for the full
// length n, return 0
if (dp[n] == -1) {
return 0;
}
// Return the maximum number of cuts for
// the rod of length n
return dp[n];
}
static void Main(string[] args) {
int n = 11;
int x = 2, y = 3, z = 5;
Console.WriteLine(maximizeTheCuts(n, x, y, z));
}}
JavaScript
// JavaScript implementation to find max cut segments // using Tabulation
// Main function to start the cutting process function maximizeTheCuts(n, x, y, z) {
// Create a table to store results of subproblems
let dp = new Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
// Check if the current length is at least x
// If so, check if the previous result
// (dp[i - x]) is valid (not -1)
// Update dp[i] by considering this cut
if (i >= x && dp[i - x] !== -1) {
dp[i] = Math.max(dp[i], dp[i - x] + 1);
}
// Similarly, check for the other two possible
// cuts (y and z)
if (i >= y && dp[i - y] !== -1) {
dp[i] = Math.max(dp[i], dp[i - y] + 1);
}
if (i >= z && dp[i - z] !== -1) {
dp[i] = Math.max(dp[i], dp[i - z] + 1);
}
// If no valid cut was found for length i,
if (dp[i] === 0) {
dp[i] = -1;
}
}
// If no valid cuts are found for the full
// length n, return 0
if (dp[n] === -1) {
return 0;
}
// Return the maximum number of cuts for
// the rod of length n
return dp[n];}
let n = 11; let x = 2, y = 3, z = 5;
console.log(maximizeTheCuts(n, x, y, z));
`