【多重背包】Transport Ship

【来源】

  2018年焦作网络赛

【参考博客】

  https://blog.csdn.net/baymax520/article/details/82719454 

【题意】

  有N种船只,每种船只的载货量为v[i],每种船只有2^c[i]-1种,有q次询问,每次问有多少种载货方式填满容量s。

【思路】

  如果用裸的01背包的话时间复杂度是O(N*2^c[i]*10000),显然是会超时的,但是我们可以把每一种船只合并,比如船只有2^x-1艘的话,就拆成2^0+2^1+2^2+...+2^(x-1),1~2^x-1的任意一个数都可以由拆分出来的数组成,将所有合并后的结果进行一次01背包即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 const int M = 1e4+5;
 7 const int mod = 1e9+7;
 8 ll dp[M],v[25],c[25],V;
 9 int main()
10 {
11     int t,n,Q,s;
12     scanf("%d",&t);
13     while(t--){
14         scanf("%d%d",&n,&Q);
15         for(int i=1;i<=n;i++)
16             scanf("%d%d",&v[i],&c[i]);
17 
18         memset(dp,0,sizeof dp );
19         dp[0] = 1 ;
20         for(int i=1;i<=n;i++){
21             for(int k=0;k<c[i];k++){
22                 V = 1ll* v[i] << k ;
23                 for(int j=M-1;j>=V;j--){
24                     dp[j] += dp[j-V];
25                     dp[j] %= mod ;
26                 }
27             }
28         }
29         for(int i=1;i<=Q;i++){
30             scanf("%d",&s);
31             printf("%lld
",dp[s]);
32         }
33     }
34     return 0;
35 }
View Code
原文地址:https://www.cnblogs.com/Osea/p/11297920.html