Given 4 numbers N, M, X, Y. which represent N numbers for the first item and M numbers for the second item, the task is to find the number of arrangements of N + M items together such that not more than X first items and not more than Y second items are placed successively.
Examples:
Input: N = 2, M = 1, X = 1, Y = 10
Output: 1
Explanation: Let’s mark the first item as 1Â
and the second item as 2 the only arrangement possible is 121.Input: N = 2, M = 3, X = 1, Y = 2
Output: 5
Explanation: Lets mark the first element as 1 and second element as 2.Â
The arrangements possible are 12122, 12212, 21212, 21221, 22121.
Approach: To solve the problem follow the below observations and steps:
There are many possibilities of placing up to X first items and then up to Y second items. So to check each and every possibility we can use dynamic programming.
Since at each step N, M, X, and Y will change so there will be 4 states of dp[] array.Â
Let the f(n, m, x, y) represents number of ways to choose to make a valid arrangement with x consecutive 1st type elements and y consecutive elements.
So there can be 2 cases: We place first type element: f(n-1, m, x-1, y) or
we choose second type of element: f(n, m-1, x, y-1)So f(n, m, x, y) = f(n – 1, m, x – 1, y) + f(n, m – 1, x, y – 1)
Here is the case that if m or n becomes 0 then on the next iteration we cannot use another consecutive element if 1st or 2nd type.
Follow the below steps to implement the approach:
- Create a recursive function and a 4dimensional array (say dp[]) that will store each of the states.
- Recursively call the functions as mentioned above maintaining the mentioned edge case.
- Return the final value stored at dp[N][M][X][Y] as the required answer.
Below is the implementation of the above approach:Â
C++14
// C++ code to implement the approach. Â
#include <bits/stdc++.h> using namespace std; Â
// dp array int dp[101][101][11][11]; Â
// To store original value of X, Y int limit_f = 0, limit_s = 0; Â
// Function to find number of ways int numofways( int n, int m, int x, int y) {     // Base case if n1+n2 is 0 that all     // items are placed then 1 arrangement     // is complete     if (n + m == 0)         return 1; Â
    int f = 0, s = 0;     if (dp[n][m][x][y] != -1) Â
        // The value is precomputed or not         return dp[n][m][x][y]; Â
    // If 1st item can be placed     if (n > 0 && x > 0) Â
        // Since we place the first item         // there are limit_s second items         // can be placed consecutively         f = numofways(n - 1, m, x - 1, limit_s);     if (m > 0 && y > 0) Â
        // Since we place the second item there         // are limit_f first item can be         // placed consecutively         s = numofways(n, m - 1, limit_f, y - 1); Â
    // Total number of arrangements is     // addition of 2     return dp[n][m][x][y] = (f + s); } Â
// Driver code int main() { Â Â Â Â int N = 2, M = 3, X = 1, Y = 2; Â Â Â Â limit_f = X, limit_s = Y; Â
    // Initialization     for ( int i = 0; i <= N; i++) {         for ( int j = 0; j <= M; j++) {             for ( int k = 0; k <= X; k++) {                 for ( int m = 0; m <= Y; m++)                     dp[i][j][k][m] = -1;             }         }     } Â
    // Function call     cout << numofways(N, M, X, Y) << endl;     return 0; } |
Java
// Java code to implement the approach. import java.io.*; Â
class GFG {      // dp array   static int dp[][][][] = new int [ 101 ][ 101 ][ 11 ][ 11 ]; Â
  // To store original value of X, Y   static int limit_f = 0 , limit_s = 0 ; Â
  // Function to find number of ways   public static int numofways( int n, int m, int x, int y)   {     // Base case if n1+n2 is 0 that all     // items are placed then 1 arrangement     // is complete     if (n + m == 0 )       return 1 ; Â
    int f = 0 , s = 0 ;     if (dp[n][m][x][y] != - 1 ) Â
      // The value is precomputed or not       return dp[n][m][x][y]; Â
    // If 1st item can be placed     if (n > 0 && x > 0 ) Â
      // Since we place the first item       // there are limit_s second items       // can be placed consecutively       f = numofways(n - 1 , m, x - 1 , limit_s);     if (m > 0 && y > 0 ) Â
      // Since we place the second item there       // are limit_f first item can be       // placed consecutively       s = numofways(n, m - 1 , limit_f, y - 1 ); Â
    // Total number of arrangements is     // addition of 2     return dp[n][m][x][y] = (f + s);   } Â
  // Driver Code   public static void main(String[] args)   {     int N = 2 , M = 3 , X = 1 , Y = 2 ;     limit_f = X;     limit_s = Y; Â
    // Initialization     for ( int i = 0 ; i <= N; i++) {       for ( int j = 0 ; j <= M; j++) {         for ( int k = 0 ; k <= X; k++) {           for ( int m = 0 ; m <= Y; m++)             dp[i][j][k][m] = - 1 ;         }       }     } Â
    // Function call     System.out.println(numofways(N, M, X, Y));   } } Â
// This code is contributed by Rohit Pradhan |
Python3
# dp array dp = [ - 1 ] * 101 ; for i in range ( 0 , len (dp)): Â Â dp[i] = [ - 1 ] * 101 Â Â for j in range ( 0 , len (dp[i])): Â Â Â Â dp[i][j] = [ - 1 ] * 11 Â Â Â Â for k in range ( 0 , len (dp[i][j])): Â Â Â Â Â Â dp[i][j][k] = [ - 1 ] * 11 Â
# To store original value of X, Y limit_f = 0 limit_s = 0 Â
# Function to find number of ways def numofways(n, m, x, y):        # Base case if n1+n2 is 0 that all     # items are placed then 1 arrangement     # is complete     if (n + m is 0 ):         return 1 Â
    f = 0     s = 0     if (dp[n][m][x][y] ! = - 1 ): Â
        # The value is precomputed or not         return dp[n][m][x][y] Â
    # If 1st item can be placed     if (n > 0 and x > 0 ): Â
        # Since we place the first item         # there are limit_s second items         # can be placed consecutively         f = numofways(n - 1 , m, x - 1 , limit_s)     if (m > 0 and y > 0 ): Â
        # Since we place the second item there         # are limit_f first item can be         # placed consecutively         s = numofways(n, m - 1 , limit_f, y - 1 ) Â
    # Total number of arrangements is     # addition of 2     dp[n][m][x][y] = (f + s)     return dp[n][m][x][y]    # Driver code N = 2 M = 3 X = 1 Y = 2 limit_f = X limit_s = Y Â
# Initialization for i in range ( 0 ,N + 1 ): Â Â for j in range ( 0 ,M + 1 ): Â Â Â Â for k in range ( 0 ,X + 1 ): Â Â Â Â Â Â for m in range ( 0 ,Y + 1 ): Â Â Â Â Â Â Â Â dp[i][j][k][m] = - 1 Â
# Function call print (numofways(N, M, X, Y)) Â
# This code is contributed by akashish__ |
C#
// C# code to implement the approach using System; Â
public class GFG {   // dp array   public static int [,,,] dp = new int [101,101,11,11];   // To store original value of X, Y   public static int limit_f = 0;   public static int limit_s = 0; Â
  // Function to find number of ways   public static int numofways( int n, int m, int x, int y)   {          // Base case if n1+n2 is 0 that all     // items are placed then 1 arrangement     // is complete     if (n + m == 0)       return 1; Â
    int f = 0, s = 0;     if (dp[n,m,x,y] != -1) Â
      // The value is precomputed or not       return dp[n,m,x,y]; Â
    // If 1st item can be placed     if (n > 0 && x > 0) Â
      // Since we place the first item       // there are limit_s second items       // can be placed consecutively       f = numofways(n - 1, m, x - 1, limit_s);     if (m > 0 && y > 0) Â
      // Since we place the second item there       // are limit_f first item can be       // placed consecutively       s = numofways(n, m - 1, limit_f, y - 1); Â
    // Total number of arrangements is     // addition of 2     return dp[n,m,x,y] = (f + s);   } Â
  public static void Main( string [] args)   {     int N = 2, M = 3, X = 1, Y = 2;     limit_f = X; limit_s = Y; Â
    // Initialization     for ( int i = 0; i <= N; i++) {       for ( int j = 0; j <= M; j++) {         for ( int k = 0; k <= X; k++) {           for ( int m = 0; m <= Y; m++)             dp[i,j,k,m] = -1;         }       }     } Â
    // Function call     Console.WriteLine(numofways(N, M, X, Y)); Â
  } } Â
// This code is contributed by ksam24000 |
Javascript
<script>        // JavaScript code for the above approach        let dp = new Array(101);        for (let i = 0; i < dp.length; i++) {            dp[i] = new Array(101);            for (let j = 0; j < dp[i].length; j++) {                dp[i][j] = new Array(11);                for (let k = 0; k < dp[i][j].length; k++) {                    dp[i][j][k] = new Array(11);                }            } Â
       } Â
       // To store original value of X, Y        let limit_f = 0, limit_s = 0; Â
       // Function to find number of ways        function numofways(n, m, x, y)        {                    // Base case if n1+n2 is 0 that all            // items are placed then 1 arrangement            // is complete            if (n + m == 0)                return 1; Â
           let f = 0, s = 0;            if (dp[n][m][x][y] != -1) Â
               // The value is precomputed or not                return dp[n][m][x][y]; Â
           // If 1st item can be placed            if (n > 0 && x > 0) Â
               // Since we place the first item                // there are limit_s second items                // can be placed consecutively                f = numofways(n - 1, m, x - 1, limit_s);            if (m > 0 && y > 0) Â
               // Since we place the second item there                // are limit_f first item can be                // placed consecutively                s = numofways(n, m - 1, limit_f, y - 1); Â
           // Total number of arrangements is            // addition of 2            return dp[n][m][x][y] = (f + s);        } Â
       // Driver code Â
       let N = 2, M = 3, X = 1, Y = 2;        limit_f = X, limit_s = Y; Â
       // Initialization        for (let i = 0; i <= N; i++) {            for (let j = 0; j <= M; j++) {                for (let k = 0; k <= X; k++) {                    for (let m = 0; m <= Y; m++)                        dp[i][j][k][m] = -1;                }            }        } Â
       // Function call        document.write(numofways(N, M, X, Y)); Â
// This code is contributed by Potta Lokesh Â
   </script> |
5
Time Complexity: O(N * M * X * Y)
Auxiliary Space: O(N * M * X * Y),
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Below is the implentation of the above approach:
C++
// C++ code to implement the approach. Â
#include <bits/stdc++.h> using namespace std; Â
// Function to find number of ways int numofways( int n, int m, int x, int y) {     // dp array     int dp[n + 1][m + 1][x + 1][y + 1]; Â
    // initialize dp with base cases     memset (dp, 0, sizeof (dp)); Â
    // Base case initialization     for ( int i = 0; i <= n; i++) {         for ( int j = 0; j <= m; j++) {             for ( int k = 0; k <= x; k++) {                 for ( int l = 0; l <= y; l++) {                     if (i + j == 0)                         dp[i][j][k][l] = 1;                 }             }         }     } Â
    // iterate over subproblems and get the current     // solution for previous computations     for ( int i = 0; i <= n; i++) {         for ( int j = 0; j <= m; j++) {             for ( int k = 0; k <= x; k++) {                 for ( int l = 0; l <= y; l++) {                     if (dp[i][j][k][l] == 0) {                         int f = 0, s = 0;                         if (i > 0 && k > 0)                             f = dp[i - 1][j][k - 1][y];                         if (j > 0 && l > 0)                             s = dp[i][j - 1][x][l - 1];                         dp[i][j][k][l] = f + s;                     }                 }             }         }     } Â
    // return answer     return dp[n][m][x][y]; } Â
// Driver code int main() { Â Â Â Â int N = 2, M = 3, X = 1, Y = 2; Â
    // Function call     cout << numofways(N, M, X, Y) << endl;     return 0; } |
Python3
def num_of_ways(n, m, x, y):     # Initialize dp array with zeros     dp = [[[[ 0 for _ in range (y + 1 )] for _ in range (x + 1 )] for _ in range (m + 1 )] for _ in range (n + 1 )] Â
    # Base case initialization     for i in range (n + 1 ):         for j in range (m + 1 ):             for k in range (x + 1 ):                 for l in range (y + 1 ):                     if i + j = = 0 :                         dp[i][j][k][l] = 1 Â
    # Iterate over subproblems and compute the current solution based on previous computations     for i in range (n + 1 ):         for j in range (m + 1 ):             for k in range (x + 1 ):                 for l in range (y + 1 ):                     if dp[i][j][k][l] = = 0 :                         f, s = 0 , 0                         if i > 0 and k > 0 :                             f = dp[i - 1 ][j][k - 1 ][y]                         if j > 0 and l > 0 :                             s = dp[i][j - 1 ][x][l - 1 ]                         dp[i][j][k][l] = f + s Â
    # Return the answer     return dp[n][m][x][y] Â
# Driver code if __name__ = = "__main__" : Â Â Â Â N, M, X, Y = 2 , 3 , 1 , 2 Â
    # Function call     print (num_of_ways(N, M, X, Y)) |
5
Time Complexity: O(N * M * X * Y)
Auxiliary Space: O(N * M * X * Y),
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!