【来源】
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 }