C++|两种类型的N和M物品的排列,当每种类型的最大X和Y物品可以连续时的教程

48 阅读3分钟

给出4个数字N,M,X,Y,分别代表第一件物品的N个数字和第二件物品的M个数字,任务是找出N+M的物品排列在一起的数量,使第一件物品不超过X,第二件物品不超过Y。

例子。

输入。 N = 2, M = 1, X = 1, Y = 10
输出。 1
**解释。**我们把第一项标为1
,第二项标为2,唯一可能的排列是121。

输入。 N = 2, M = 3, X = 1, Y = 2
输出。 5
**解释。**让我们把第一项标记为1,第二项标记为2。
可能的排列是12122, 12212, 21212, 21221, 22121。

办法:要解决这个问题,请遵循以下的观察和步骤。

有许多可能性,先放X个项目,再放Y个项目。所以要检查每一种可能性,我们可以使用动态编程。

由于每一步N、M、X和Y都会发生变化,所以dp[]数组会有4种状态。

让f(n, m, x, y)代表选择以x个连续的第一类元素和y个连续的元素进行有效排列的方法的数量。

所以可以有2种情况。我们放置第一类元素:f(n-1, m, x-1, y)或者
我们选择第二类元素:f(n, m-1, x, y-1)

所以 f(n, m, x, y) = f(n - 1, m, x - 1, y) + f(n, m - 1, x, y - 1)

这里的情况是,如果mn变成了0,那么在下一次迭代中,我们不能使用另一个连续的元素,如果第1或第2类型。

按照下面的步骤来实现这个方法。

  • 创建一个递归函数和一个四维数组(例如dp[]),用来存储每个状态。
  • 递归调用上面提到的函数,保持提到的边缘情况。
  • 返回存储在**dp[N][M][X][Y]**的最终值作为所需的答案。

下面是上述方法的实现。

C++

// 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;
}

输出

5

时间复杂度。 O(N * M * X * Y)
辅助空间。 O(N * M * X * Y)。