Maximize the number of segments of length p, q and r - GeeksforGeeks

29 Nov, 2021
Given a rod of length L, the task is to cut the rod in such a way that the total number of segments of length p, q and r is maximized. The segments can only be of length p, q, and r. 
Examples: 
Input: l = 11, p = 2, q = 3, r = 5 Output: 5 Segments of 2, 2, 2, 2 and 3
Input: l = 7, p = 2, q = 5, r = 5 Output: 2 Segments of 2 and 5
Approach 1:
This can be visualized as a classical recursion problem , which further narrows down to memoization ( top-down ) method of Dynamic Programming. Initially , we have length l present with us , we’d have three size choices to cut from this , either we can make a cut of length p , or q , or r. Let’s say we made a cut of length p , so the remaining length would be l-p and similarly with cuts q & r resulting in remaining lengths l-q & l-r respectively. We will call recursive function for the remaining lengths and at any subsequent instance we’ll have these three choices. We will store the answer from all these recursive calls & take the maximum out of them +1 as at any instance we’ll have 1 cut from this particular call as well. Also , note that the recursive call would be made if and only if the available length is greater than length we want to cut i.e. suppose p=3 , and after certain recursive calls the available length is 2 only , so we can’t cut this line in lengths of p anymore.
Below is the pseudocode for the same:
if(l==0)  // Base Case
  return 0;
  
  
int a,b,c;
if(p<=l)
   a=func(l-p,p,q,r);
if(q<=l)
   b=func(l-q,p,q,r);
if(r<=l)
   c=func(l-r,p,q,r);
return 1+max({a,b,c});
Below is the recursion tree for l=4,p=2,q=1 and r=1:
Recursion Tree for l=4 , p=2 ,q=1 and r=1
One can clearly observe that at each call , the given length ( 4 initially ) is divided into 3 different subparts. Also , we can see that the recursion is being repeated for certain entries ( Red arrow represents repetitive call for l=2, Yellow for l=3 and Blue for l=1). Therefore , we can memoize the results in any container or array , so that repetition of same recursive calls is avoided.
Now , the above pseudocode changes to :
vector<int> dp(10005,-1);         // Initialise DP Table ( Array can also be used )


if(l==0)                         // Base Case
 return 0;
 
if(dp[l]!=-1)                 // If already memoized , return from here only
   return dp[l];
int a,b,c;
if(p<=l)
  a=func(l-p,p,q,r);
if(q<=l)
  b=func(l-q,p,q,r);
if(r<=l)
  c=func(l-r,p,q,r);
  
  
return dp[l]=1+max({a,b,c});          // Memoize the result in the dp table & return
Let’s now follow the code for implementation of the above code :
C++
//C++ Code to find maximum number of cut segments// Memoization DP #include <bits/stdc++.h>using namespace std; //Function to find the maximum number of cuts.int dp[10005];     int func(int l, int p, int q, int r){    if(l==0)       return 0;                               // Base Case                 if(dp[l]!=-1)                              // If already memoized        return dp[l];              int a(INT_MIN),b(INT_MIN),c(INT_MIN);         // Intitialise a,b,& c with INT_MIN        if(p<=l)                                      // If Possible to make a cut of length p        a=func(l-p,p,q,r);        if(q<=l)                                      // If possible to make a cut of length q        b=func(l-q,p,q,r);        if(r<=l)                                      // If possible to make a cut of length r        c=func(l-r,p,q,r);        return dp[l]=1+max({a,b,c});                    // Memoize & return         }     int maximizeTheCuts(int l, int p, int q, int r){    memset(dp,-1,sizeof(dp));                 // Set Lookup table to -1    int ans=func(l,p,q,r);                    // Utility function call             if(ans<0)       return 0;                        // If returned answer is negative , that means cuts are not possible    return ans; } int main(){   int l,p,q,r;  cout<<"ENTER THE LENGTH OF THE ROD "<<endl;  cin>>l;     cout<<"ENTER THE VALUES OF p,q & r "<<endl;  cin>>p>>q>>r;     cout<<"THE MAXIMUM NUMBER OF SEGMENTS THAT CAN BE CUT OF LENGTH p,q & r FROM A ROD OF LENGTH l are "<<maximizeTheCuts(l,p,q,r)<<endl;    return 0;}
Time Complexity : O(n) where n is the length of rod or line segment that has to be cut.
Space Complexity : O(n) where n is the length of rod or line segment that has to be cut.
Approach 2: 
As the solution for a maximum number of cuts that can be made in a given length depends on the maximum number of cuts previously made in shorter lengths, this question could be solved by the approach of Dynamic Programming. Suppose we are given a length ‘l’. For finding the maximum number of cuts that can be made in length ‘l’, find the number of cuts made in shorter previous length ‘l-p’, ‘l-q’, ‘l-r’ lengths respectively. The required answer would be the max(l-p,l-q,l-r)+1 as one more cut should be needed after this to cut length ‘l’. So for solving this problem for a given length, find the maximum number of cuts that can be made in lengths ranging from ‘1’ to ‘l’. 
Example:  
l = 11, p = 2, q = 3, r = 5 Analysing lengths from 1 to 11: 
Not possible to cut->0Possible cut is of lengths 2->1 (2)Possible cut is of lengths 3->1 (3)Possible cuts are of lengths max(arr[4-2],arr[4-3])+1->2 (2,2)Possible cuts are of lengths max(arr[5-2],arr[5-3])+1->2 (2,3)Possible cuts are of lengths max(arr[6-2],arr[6-3],arr[6-5])+1->3 (2,2,2)Possible cuts are of lengths max(arr[7-2],arr[7-3],arr[7-5])+1->3 (2,3,2) or (2,2,3)Possible cuts are of lengths max(arr[8-2],arr[8-3],arr[8-5])+1->4 (2,2,2,2)Possible cuts are of lengths max(arr[9-2],arr[9-3],arr[9-5])+1->4 (2,3,2,2) or (2,2,3,2) or (2,2,2,3)Possible cuts are of lengths max(arr[10-2],arr[10-3],arr[10-5])+1->5 (2,2,2,2,2)Possible cuts are of lengths max(arr[11-2],arr[11-3],arr[11-5])+1->5 (2,3,2,2,2) or (2,2,3,2,2) or (2,2,2,3,2) or (2,2,2,2,3)
Not possible to cut->0
Possible cut is of lengths 2->1 (2)
Possible cut is of lengths 3->1 (3)
Possible cuts are of lengths max(arr[4-2],arr[4-3])+1->2 (2,2)
Possible cuts are of lengths max(arr[5-2],arr[5-3])+1->2 (2,3)
Possible cuts are of lengths max(arr[6-2],arr[6-3],arr[6-5])+1->3 (2,2,2)
Possible cuts are of lengths max(arr[7-2],arr[7-3],arr[7-5])+1->3 (2,3,2) or (2,2,3)
Possible cuts are of lengths max(arr[8-2],arr[8-3],arr[8-5])+1->4 (2,2,2,2)
Possible cuts are of lengths max(arr[9-2],arr[9-3],arr[9-5])+1->4 (2,3,2,2) or (2,2,3,2) or (2,2,2,3)
Possible cuts are of lengths max(arr[10-2],arr[10-3],arr[10-5])+1->5 (2,2,2,2,2)
Possible cuts are of lengths max(arr[11-2],arr[11-3],arr[11-5])+1->5 (2,3,2,2,2) or (2,2,3,2,2) or (2,2,2,3,2) or (2,2,2,2,3)
Algorithm: 
Initialise an array DP[]={-1} and DP[0]=0.Run a loop from ‘1’ to ‘l’If DP[i]=-1 means it’s not possible to divide it using giving segments p,q,r so continue;DP[i+p]=max(DP[i+p],DP[i]+1)DP[i+q]=max(DP[i+q],DP[i]+1)DP[i+r]=max(DP[i+r],DP[i]+1)print DP[l]
Initialise an array DP[]={-1} and DP[0]=0.
Run a loop from ‘1’ to ‘l’
If DP[i]=-1 means it’s not possible to divide it using giving segments p,q,r so continue;
DP[i+p]=max(DP[i+p],DP[i]+1)
DP[i+q]=max(DP[i+q],DP[i]+1)
DP[i+r]=max(DP[i+r],DP[i]+1)
print DP[l]
Pseudo Code: 
DP[l+1]={-1}
DP[0]=0
for(i from 0 to l)
  if(DP[i]==-1)
  continue
  DP[i+p]=max(DP[i+p],DP[i]+1)
  DP[i+q]=max(DP[i+q],DP[i]+1)
  DP[i+r]=max(DP[i+r],DP[i]+1)

print(DP[l])
Implementation: 
C++
Java
Python3
C#
Javascript
// C++ program to maximize the number// of segments of length p, q and r#include <bits/stdc++.h>using namespace std; // Function that returns the maximum number// of segments possibleint findMaximum(int l, int p, int q, int r){     // Array to store the cut at each length    int dp[l + 1];     // All values with -1    memset(dp, -1, sizeof(dp));     // if length of rod is 0 then total cuts will be 0    // so, initialize the dp[0] with 0    dp[0] = 0;     for (int i = 0; i <= l; i++) {         // if certain length is not possible        if (dp[i] == -1)            continue;         // if a segment of p is possible        if (i + p <= l)            dp[i + p] = max(dp[i + p], dp[i] + 1);         // if a segment of q is possible        if (i + q <= l)            dp[i + q] = max(dp[i + q], dp[i] + 1);         // if a segment of r is possible        if (i + r <= l)            dp[i + r] = max(dp[i + r], dp[i] + 1);    }    // if no segment can be cut then return 0    if (dp[l] == -1) {        dp[l] = 0;    }    // return value corresponding to length l    return dp[l];} // Driver Codeint main(){    int l = 11, p = 2, q = 3, r = 5;     // Calling Function    int ans = findMaximum(l, p, q, r);    cout << ans;     return 0;}
// Java program to maximize// the number of segments// of length p, q and rimport java.io.*; class GFG {     // Function that returns    // the maximum number    // of segments possible    static int findMaximum(int l, int p, int q, int r)    {         // Array to store the        // cut at each length        int dp[] = new int[l + 1];         // All values with -1        for (int i = 0; i < l + 1; i++)            dp[i] = -1;         // if length of rod is 0        // then total cuts will        // be 0 so, initialize        // the dp[0] with 0        dp[0] = 0;         for (int i = 0; i <= l; i++) {             // if certain length            // is not possible            if (dp[i] == -1)                continue;             // if a segment of            // p is possible            if (i + p <= l)                dp[i + p] = Math.max(dp[i + p], dp[i] + 1);             // if a segment of            // q is possible            if (i + q <= l)                dp[i + q] = Math.max(dp[i + q], dp[i] + 1);             // if a segment of            // r is possible            if (i + r <= l)                dp[i + r] = Math.max(dp[i + r], dp[i] + 1);        }         // if no segment can be cut then return 0        if (dp[l] == -1) {            dp[l] = 0;        }        // return value corresponding        // to length l        return dp[l];    }     // Driver Code    public static void main(String[] args)    {        int l = 11, p = 2, q = 3, r = 5;         // Calling Function        int ans = findMaximum(l, p, q, r);        System.out.println(ans);    }} // This code is contributed// by anuj_67.
# Python 3 program to# maximize the number# of segments of length# p, q and r # Function that returns# the maximum number# of segments possible  def findMaximum(l, p, q, r):     # Array to store the cut    # at each length    # All values with -1    dp = [-1]*(l + 1)     # if length of rod is 0 then    # total cuts will be 0    # so, initialize the dp[0] with 0    dp[0] = 0     for i in range(l+1):         # if certain length is not        # possible        if (dp[i] == -1):            continue         # if a segment of p is possible        if (i + p <= l):            dp[i + p] = (max(dp[i + p],                             dp[i] + 1))         # if a segment of q is possible        if (i + q <= l):            dp[i + q] = (max(dp[i + q],                             dp[i] + 1))         # if a segment of r is possible        if (i + r <= l):            dp[i + r] = (max(dp[i + r],                             dp[i] + 1))     # if no segment can be cut then return 0    if dp[l] == -1:        dp[l] = 0    # return value corresponding    # to length l    return dp[l]  # Driver Codeif __name__ == "__main__":    l = 11    p = 2    q = 3    r = 5     # Calling Function    ans = findMaximum(l, p, q, r)    print(ans) # This code is contributed by# ChitraNayal
// C# program to maximize// the number of segments// of length p, q and rusing System; class GFG {     // Function that returns    // the maximum number    // of segments possible    static int findMaximum(int l, int p,                           int q, int r)    {         // Array to store the        // cut at each length        int[] dp = new int[l + 1];         // All values with -1        for (int i = 0; i < l + 1; i++)            dp[i] = -1;         // if length of rod is 0        // then total cuts will        // be 0 so, initialize        // the dp[0] with 0        dp[0] = 0;         for (int i = 0; i <= l; i++) {             // if certain length            // is not possible            if (dp[i] == -1)                continue;             // if a segment of            // p is possible            if (i + p <= l)                dp[i + p] = Math.Max(dp[i + p],                                     dp[i] + 1);             // if a segment of            // q is possible            if (i + q <= l)                dp[i + q] = Math.Max(dp[i + q],                                     dp[i] + 1);             // if a segment of            // r is possible            if (i + r <= l)                dp[i + r] = Math.Max(dp[i + r],                                     dp[i] + 1);        }         // if no segment can be cut then return 0        if (dp[l] == -1) {            dp[l] = 0;        }        // return value corresponding        // to length l        return dp[l];    }     // Driver Code    public static void Main()    {        int l = 11, p = 2, q = 3, r = 5;         // Calling Function        int ans = findMaximum(l, p, q, r);        Console.WriteLine(ans);    }} // This code is contributed// by anuj_67.
<script>// Javascript program to maximize// the number of segments// of length p, q and r         // Function that returns    // the maximum number    // of segments possible    function findMaximum(l,p,q,r)    {        // Array to store the        // cut at each length        let dp = new Array(l + 1);          // All values with -1        for (let i = 0; i < l + 1; i++)            dp[i] = -1;          // if length of rod is 0        // then total cuts will        // be 0 so, initialize        // the dp[0] with 0        dp[0] = 0;          for (let i = 0; i <= l; i++) {              // if certain length            // is not possible            if (dp[i] == -1)                continue;              // if a segment of            // p is possible            if (i + p <= l)                dp[i + p] = Math.max(dp[i + p], dp[i] + 1);              // if a segment of            // q is possible            if (i + q <= l)                dp[i + q] = Math.max(dp[i + q], dp[i] + 1);              // if a segment of            // r is possible            if (i + r <= l)                dp[i + r] = Math.max(dp[i + r], dp[i] + 1);        }          // if no segment can be cut then return 0        if (dp[l] == -1) {            dp[l] = 0;        }        // return value corresponding        // to length l        return dp[l];    }         // Driver Code    let l = 11, p = 2, q = 3, r = 5;    // Calling Function    let ans = findMaximum(l, p, q, r);         document.write(ans);      // This code is contributed by rag2127</script>
5
Complexity Analysis: 
Time Complexity: O(N). Use of a single for-loop till length ‘N’.
Auxiliary Space: O(N). Use of an array ‘DP’ to keep track of segments
Note: This problem can also be thought of as a minimum coin change problem because we are given a certain length to acquire which is the same as the value of the amount whose minimum change is needed. Now the x,y,z are the same as the denomination of the coin given. So length is the same as the amount and x y z are the same as denominations, thus we need to change only one condition that is instead of finding minimum we need to find the maximum and we will get the answer. As the minimum coin change problem is the basic dynamic programming question so this will help to solve this question also.
The condition we need to change in minimum coin change problem
for(ll i=1;i<=n;i++)
{
     for(ll j=1;j<=3;j++)
     {
          if(i>=a[j]&&m[i-a[j]]!=-1)
          {
               dp[i]=max(dp[i],1+dp[i-a[j]]);
          }
     }
}
vt_m
ukasp
bidibaaz123
techwithintechtofar
rg_1999
rag2127
tusharsingh432
singhvishal240891
24pranshu
Algorithms-Dynamic Programming
Arrays
Greedy Algorithms
Competitive Programming
Arrays
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Multistage Graph (Shortest Path)
Breadth First Traversal ( BFS ) on a 2D array
Shortest path in a directed graph by Dijkstra’s algorithm
5 Best Books for Competitive Programming
5 Best Languages for Competitive Programming
Most important type of Algorithms
Difference between Backtracking and Branch-N-Bound technique
String hashing using Polynomial rolling hash function
Graph implementation using STL for competitive programming | Set 2 (Weighted graph)
Implementing upper_bound() and lower_bound() in C