多重集组合数 (DP)

输入:

n=3

m=3

a={1,2,3}

M=10000

输出:

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个的组合总数

 

 

复杂度:O(nm)

 1 int n,m;
 2 int a[MAX];
 3 
 4 int dp[MAX][MAX];  //数组
 5 
 6 void solve()
 7 {
 8     //一个都不取的方法总是只有一种
 9     for(int i=0; i<=n; i++){
10         dp[i][0]=1;
11     }
12     for(int i=0; i<=n; i++){
13         for(int j=1; j<=m; j++){
14             if(j-1-a[i]>=0){
15                 //在有取余的情况下,要避免减法运算的结果出现负数
16                 dp[i+1][j]=(dp[i+1][j-1]+dp[i][j]-dp[i][j-1-a[i]]+M)%M;
17             }
18             else{
19                 dp[i+1][j]=(dp[i+1][j-1]+dp[i][j])%M;
20             }
21         }
22     }
23     printf("%d\n",dp[n][m]);
24 }

 

posted @ 2016-03-03 21:02  Vmetrio  阅读(740)  评论(0)    收藏  举报