http://acm.hdu.edu.cn/showproblem.php?pid=2844
【题意】
- 给定n种价值为Ci,个数为Wi的硬币,问在1~V中的这些数中哪些数能由这些硬币组成?
【思路】
- 多重背包,二进制优化,时间复杂度为O(V*log∑ni)
【Accepted】
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 10 using namespace std; 11 typedef long long ll; 12 const int maxn=1e5+2; 13 14 int n,v; 15 int c[maxn],w[maxn]; 16 int dp[maxn]; 17 void ZOP(int cost,int wei) 18 { 19 for(int i=v;i>=cost;i--) 20 { 21 dp[i]=max(dp[i],dp[i-cost]+wei); 22 } 23 } 24 25 void CPP(int cost,int wei) 26 { 27 for(int i=cost;i<=v;i++) 28 { 29 dp[i]=max(dp[i],dp[i-cost]+wei); 30 } 31 } 32 33 void MTP(int cost,int wei,int cnt) 34 { 35 if(v<=cnt*cost) 36 { 37 CPP(cost,wei); 38 return; 39 } 40 int k=1; 41 while(k<=cnt) 42 { 43 ZOP(k*cost,k*wei); 44 cnt-=k; 45 k*=2; 46 } 47 ZOP(cnt*cost,cnt*wei); 48 } 49 int main() 50 { 51 while(~scanf("%d%d",&n,&v)) 52 { 53 if(n==0&&v==0) break; 54 for(int i=0;i<n;i++) 55 { 56 scanf("%d",&c[i]); 57 } 58 for(int i=0;i<n;i++) 59 { 60 scanf("%d",&w[i]); 61 } 62 memset(dp,0,sizeof(dp)); 63 for(int i=0;i<n;i++) 64 { 65 MTP(c[i],c[i],w[i]); 66 } 67 int cnt=0; 68 for(int i=1;i<=v;i++) 69 { 70 if(dp[i]==i) 71 { 72 cnt++; 73 } 74 } 75 printf("%d ",cnt); 76 } 77 return 0; 78 }