其他分享
首页 > 其他分享> > yp多冲集合组合数

yp多冲集合组合数

作者:互联网

这里写目录标题

定义

n = 3
m = 3
a={1,2,3}
M = 10000

不同的物品可以相互区分,同种物品区分不了
问从n中选择m个方案数
6{0+0+3,0+1+2,0+2+1,1+0+2,1+1+1,1+2+0}

思路

为了不重复记数,同一种类的物品最好一次性处理好。于是我们按照如下方式进行定义
dp[i+1][j]  从前i中物品中取出j个的组合总数
为了从前i种物品中取出j个,可以从第i个物品中取出k个,再从其他i-1物品取出j-k个
所以  dp[i+1][j]   =  (k=0,min ( j,a[i] ) )  ∑ dp [ i ] [ j - k ] 
直接计算这个递推关系的话复杂度是O(nm^2^),不过因为我们有
(k=0,min(j,a[i])) ∑dp[i][j-k]= (k=0,min(j-1,a[i] )) ∑dp[i] [ j-1-k] +dp[i][j] -dp[i ][ j-1- ai] 
变形:dp[i+1][j] = dp[i+1][j-1] +dp[i][j] -dp[i][j-1-ai]     复杂度O(nm)

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
const int N = 1E2 + 7;
const int M = 1E3 + 7;
#define INF ~0ULL

int n, m;
int arr[N];
int dp[N][N];

void solve()
{
    for (int i = 0; i <= n; i++)
        dp[i][0] = 1;
    for (int i = 0; i < n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (j - 1 - arr[i] >= 0)
                dp[i + 1][j] = (dp[i + 1][j - 1] + dp[i][j] - dp[i][j - 1 - arr[i]] + M) % M;
            else
                dp[i + 1][j] = (dp[i + 1][j - 1] + dp[i][j]) % M;
        }
    }
    cout << dp[n][m] << endl;
}

int main()
{
    n=3,m=3;
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    solve();
    system("pause");
}

标签:arr,min,int,物品,多冲,集合,yp,dp,define
来源: https://blog.csdn.net/MoRan0_0/article/details/120356953