Fork me on GitHub

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 }

 



 
posted @ 2015-11-15 12:33  伊甸一点  阅读(350)  评论(0编辑  收藏  举报