Given an integer n denoting the Length of a line segment. You need to cut the line segment in such a way that the cut length of a line segment each time is either x , y or z. Here x, y, and z are integers. After performing all the cut operations, your total number of cut segments must be maximum. Return the maximum number of cut segments possible.
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
[Naive Approach] Using Recursive Exploration - O(3 ^ n) Time and O(n) Space
The idea is to explore all possible ways to cut the rod by recursively subtracting each segment length. Base cases handle exact zero or negative length. Max cuts across all options gives answer.
At each step, we try all three possible cuts of length x, y, and z. Each node represents the remaining length of the rod, and the recursion continues until a valid or invalid base case is reached.

- If n is zero, return 0
- If n is negative, return -1
- Recurse by subtracting x, y, and z separately
- Find maximum among all three recursive results
- If max is -1, return -1
- Else return max + 1
#include <algorithm>
#include <iostream>
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 maximizeCuts(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 = 4;
int x = 2, y = 1, z = 1;
cout << maximizeCuts(n, x, y, z);
return 0;
}
class GFG {
// Helper function to maximize the number of cuts
static int maxCutHelper(int n, int x, int y, int z) {
// If rod length becomes exactly 0,
// a valid set of cuts has been found
if (n == 0) {
return 0;
}
// If rod length becomes negative,
// this path is invalid
if (n < 0) {
return -1;
}
// Try cutting lengths x, y, and z
int cut1 = maxCutHelper(n - x, x, y, z);
int cut2 = maxCutHelper(n - y, x, y, z);
int cut3 = maxCutHelper(n - z, x, y, z);
// Find the maximum cuts among the three choices
int maxCut = Math.max(cut1, Math.max(cut2, cut3));
// If all choices are invalid
if (maxCut == -1) {
return -1;
}
// Count the current cut
return maxCut + 1;
}
// Function to find maximum number of cuts
static int maximizeCuts(int n, int x, int y, int z) {
int res = maxCutHelper(n, x, y, z);
// If no valid cutting is possible
return Math.max(0, res);
}
public static void main(String[] args) {
int n = 4;
int x = 2;
int y = 1;
int z = 1;
int result = maximizeCuts(n, x, y, z);
System.out.println(result);
}
}
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 + 1
def maximizeCuts(n, x, y, z):
res = maxCutHelper(n, x, y, z)
# No valid cuts found
if res == -1:
return 0
return res
if __name__ == "__main__":
n = 4
x = 2
y = 1
z = 1
print(maximizeCuts(n, x, y, z))
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;
}
static int maximizeCuts(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 = 4;
int x = 2, y = 1, z = 1;
Console.WriteLine(maximizeCuts(n, x, y, z));
}
}
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;
}
function maximizeCuts(n, x, y, z)
{
let res = maxCutHelper(n, x, y, z);
// No valid cuts found
if (res === -1)
return 0;
return res;
}
// Driver Code
let n = 4;
let x = 2;
let y = 1;
let z = 1;
console.log(maximizeCuts(n, x, y, z));
Output
4
[Better Approach] Using Top-Down DP with Memoization - O(n) Time and O(n) Space
If we take a closer look at the above recursion tree, we may observe overlapping subproblems like n-x-y and n-y-x are same.
The idea is to use memoization to avoid recomputing same subproblems. Store results for each length in memo array. Return maximum cuts possible.
Working of Approach:
- Create a memo array where memo[i] stores the maximum number of segments possible for a rod of length i.
- For each length n, recursively try all three cuts by subtracting x, y, and z.
- If n becomes 0, return 0; if it becomes negative, return -1 to indicate an invalid cut.
- Store each computed result in memo so that the same subproblem is not solved again.
- Take the maximum result from the three choices and add 1; if no valid choice exists, return 0 for the original problem.
#include <iostream>
#include <vector>
#include <algorithm>
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<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 = 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;
}
int maximizeCuts(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 =4;
int x = 2, y = 1, z = 1;
cout << maximizeCuts(n, x, y, z);
return 0;
}
import java.util.Arrays;
class GFG {
// Helper function using recursion + memoization
static int maxCutHelper(int n, int x, int y, int z, int[] memo) {
// Rod completely cut
if (n == 0) {
return 0;
}
// Invalid cut
if (n < 0) {
return -1;
}
// Return already computed result
if (memo[n] != -1) {
return memo[n];
}
// Try all three possible cuts
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 maximum among the three choices
int maxCut = Math.max(cut1, Math.max(cut2, cut3));
// No valid cut possible
if (maxCut == -1) {
return memo[n] = -1;
}
return memo[n] = maxCut + 1;
}
static int maximizeCuts(int n, int x, int y, int z) {
int[] memo = new int[n + 1];
Arrays.fill(memo, -1);
int res = maxCutHelper(n, x, y, z, memo);
return Math.max(0, res);
}
public static void main(String[] args) {
// Length of rod
int n = 4;
// Allowed cut lengths
int x = 2;
int y = 1;
int z = 1;
int result = maximizeCuts(n, x, y, z);
System.out.println(result);
}
}
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]
def maximizeCuts(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 res
if __name__ == "__main__":
n = 4
x = 2
y = 1
z = 1
print(maximizeCuts(n, x, y, z))
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];
}
static int maximizeCuts(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 = 4;
int x = 2, y = 1, z = 1;
Console.WriteLine(maximizeCuts(n, x, y, z));
}
}
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];
}
function maximizeCuts(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;
}
// Driver Code
let n = 4;
let x = 2;
let y = 1;
let z = 1;
console.log(maximizeCuts(n, x, y, z));
Output
4
[Expected Approach] Using Bottom-Up DP - O(n) Time and O(n) Space
The idea is to build DP table from 1 to n. For each length, try all three possible cuts. If previous state is valid, update current state with max cuts.
Working of Approach:
- Store the three possible cut lengths x, y, and z in an array and initialize dp with 0.
- For each possible cut length, iterate through all rod lengths from 1 to n.
- If the current length equals the cut length, one segment can be formed; otherwise, extend a previously formed valid length.
- Update dp[i] with the maximum number of segments possible using the current cut.
- After considering all three cut lengths, dp[n] gives the maximum number of segments.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int maximizeCuts(int n, int x, int y, int z)
{
vector<int> arr(3);
arr[0] = x;
arr[1] = y;
arr[2] = z;
// creating a dp[] array and initializing all values with 0.
vector<int> dp(n + 1, 0);
for (int j = 0; j < 3; j++)
{
// updating the point where we can reach from x,y,z.
for (int i = 1; i <= n; i++)
{
// we will update dp[i] if the point is x,y,z or if the
// points are visited by some combination of x,y,z.
if (i == arr[j] or (i > arr[j] and dp[i - arr[j]] > 0))
dp[i] = max(dp[i - arr[j]] + 1, dp[i]);
}
}
// returning the result.
return dp[n];
}
int main()
{
int n = 4;
int x = 2, y = 1, z = 1;
cout << maximizeCuts(n, x, y, z);
return 0;
}
import java.util.Arrays;
public class GFG {
public static int maximizeCuts(int n, int x, int y,
int z)
{
int[] arr = { x, y, z };
// creating a dp[] array and initializing all values
// with 0.
int[] dp = new int[n + 1];
Arrays.fill(dp, 0);
for (int j = 0; j < 3; j++) {
// updating the point where we can reach from
// x,y,z.
for (int i = 1; i <= n; i++) {
// we will update dp[i] if the point is
// x,y,z or if the points are visited by
// some combination of x,y,z.
if (i == arr[j]
|| (i > arr[j] && dp[i - arr[j]] > 0))
dp[i] = Math.max(dp[i - arr[j]] + 1,
dp[i]);
}
}
// returning the result.
return dp[n];
}
public static void main(String[] args)
{
int n = 4;
int x = 2, y = 1, z = 1;
System.out.println(maximizeCuts(n, x, y, z));
}
}
def maximizeCuts(n, x, y, z):
arr = [x, y, z]
# creating a dp[] array and initializing all values with 0.
dp = [0] * (n + 1)
for j in range(3):
# updating the point where we can reach from x,y,z.
for i in range(1, n + 1):
# we will update dp[i] if the point is x,y,z or if the
# points are visited by some combination of x,y,z.
if i == arr[j] or (i > arr[j] and dp[i - arr[j]] > 0):
dp[i] = max(dp[i - arr[j]] + 1, dp[i])
# returning the result.
return dp[n]
if __name__ == '__main__':
n = 4
x = 2; y = 1; z = 1
print(maximizeCuts(n, x, y, z))
using System;
public class GFG {
public static int maximizeCuts(int n, int x, int y,
int z)
{
int[] arr = { x, y, z };
// creating a dp[] array and initializing all values
// with 0.
int[] dp = new int[n + 1];
for (int j = 0; j < 3; j++) {
// updating the point where we can reach from
// x,y,z.
for (int i = 1; i <= n; i++) {
// we will update dp[i] if the point is
// x,y,z or if the points are visited by
// some combination of x,y,z.
if (i == arr[j]
|| (i > arr[j] && dp[i - arr[j]] > 0))
dp[i] = Math.Max(dp[i - arr[j]] + 1,
dp[i]);
}
}
// returning the result.
return dp[n];
}
public static void Main()
{
int n = 4;
int x = 2, y = 1, z = 1;
Console.WriteLine(maximizeCuts(n, x, y, z));
}
}
function maximizeCuts(n, x, y, z)
{
let arr = [ x, y, z ];
// creating a dp[] array and initializing all values
// with 0.
let dp = new Array(n + 1).fill(0);
for (let j = 0; j < 3; j++) {
// updating the point where we can reach from x,y,z.
for (let i = 1; i <= n; i++) {
// we will update dp[i] if the point is x,y,z or
// if the points are visited by some combination
// of x,y,z.
if (i === arr[j]
|| (i > arr[j] && dp[i - arr[j]] > 0))
dp[i] = Math.max(dp[i - arr[j]] + 1, dp[i]);
}
}
// returning the result.
return dp[n];
}
// Driver Code
let n = 4;
let x = 2, y = 1, z = 1;
console.log(maximizeCuts(n, x, y, z));
Output
4