0-1背包再修改版
题目描述
把钱花完了,所以单身了,单身了所以过双“11”,过双“11”所以把钱花完了。
今年Nova君(三号)照旧过着他暗无天日的“买买买”的双“11”,然而因为囊中羞涩,并不能够太任性。他的购物车中,列满了数不清的商品,共有N件,好多商品居然还不止一件 __(:3 」∠)_ 现在Nova君要做出一个艰难的抉择,他要从所有商品中挑出m件拼成一个订单,请问有多少种凑单的方法呢?求访法数对M的余数。
PS:同一种商品不作区分。
输入
多组测试数据(不超过100组)
每组数据两行,第一行为三个正整数N,m,M,具体意义详见描述,第二行为N个正整数a1,a2,,,an,代表第i个商品的个数
(1<=N,ai,m<=1000,2<=M<=10000)
输出
对于每组数据,输出一行,表示方法总数
输入样例
3 3 10000
1 2 3
输出样例
6
详情见代码以及注释:
题目来源:http://biancheng.love/contest/17/problem/G/index
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int N=1010; 5 int a[N]; 6 int b[N][N]; 7 int main() 8 { 9 int n,m,M; 10 while(scanf("%d%d%d",&n,&m,&M)==3) 11 { 12 for(int i = 0; i < n; i++) 13 scanf("%d",&a[i]);//每种商品的件数 14 15 for(int i = 0; i <= n; i++) 16 b[i][0] = 1; 17 18 for(int i = 0; i < n; i++)//n种商品 19 for(int j = 1; j <= m; j++)//挑出m件 20 { 21 if(j -1 - a[i] >= 0)//是否大于第i中商品件数 22 b[i+1][j] = (b[i][j] + b[i+1][j-1] - b[i][j-1-a[i]] +M)%M; 23 else 24 b[i+1][j] = (b[i][j] + b[i+1][j-1])%M; 25 } 26 printf("%d\n",b[n][m]); 27 } 28 29 }
另附背包的一些模板函数:
1 void ZoreOnePack(int cost , int weight)//0-1背包 2 { 3 for (int i = W ; i >= weight ; -- i) 4 f[i] = max(f[i],f[i-weight]+cost) ; 5 } 6 7 void CompletePack(int cost , int weight)//完全背包 8 { 9 for (int i = weight ; i <= W ; ++ i) 10 f[i] = max(f[i],f[i-weight]+cost) ; 11 } 12 13 void MultiPack(int cost , int weight , int num)//多重背包 14 { 15 if (num*weight>=W) 16 CompletePack(cost,weight) ; 17 else 18 { 19 int k = 1 ; 20 while (k<num) 21 { 22 ZoreOnePack(cost*k,weight*k) ; 23 num -= k ; 24 k += k ; 25 } 26 ZoreOnePack(cost*num,weight*num) ; 27 } 28 } 29 30 void TwoZoreOnePack(int cost , int weight , int many) 31 { 32 for (int i = W ; i >= weight ; -- i) 33 for (int j = M ; j >= many ; -- j) 34 two[i][j] = max(two[i][j],two[i-weight][j-many]+cost) ; 35 } 36 37 void TwoCompletePack(int cost ,int weight ,int many) 38 { 39 for (int i = weight ; i <= W ; ++ i) 40 for (int j = many ; j <= W ; ++ j) 41 two[i][j] = max(two[i][j],two[i-weight][j-many]+cost) ; 42 } 43 44 void TwoMultiPack(int cost ,int weight , int many , int num) 45 { 46 if (num*weight>=W&&num*many>=M) 47 TwoCompletePack(cost,weight,many) ; 48 else 49 { 50 int k = 1 ; 51 while (k<num) 52 { 53 TwoZoreOnePack(cost*k,weight*k,many*k) ; 54 num -= k ; 55 k += k ; 56 } 57 TwoZoreOnePack(cost*num,weight*num,many*num) ; 58 } 59 }
作者: 伊甸一点
出处: http://www.cnblogs.com/zpfbuaa/
本文版权归作者伊甸一点所有,欢迎转载和商用(须保留此段声明),且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文链接 如有问题, 可邮件(zpflyfe@163.com)咨询.