hdu1059 多重背包(转换为01背包二进制优化)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1059
之前写过一个多重背包二进制优化的博客,不懂请参考:http://www.cnblogs.com/a-clown/p/5953847.html
//之前WA了无数次。。心塞。。。
两种思路,都可以。
代码1:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define ll long long int p[205],w[205],c[205]; int dp[105]; int main() { int T; cin>>T; while(T--) { int n,m; cin>>n>>m; for(int i=1; i<=m; i++) cin>>p[i]>>w[i]>>c[i]; memset(dp,0,sizeof(dp)); for(int i=1; i<=m; i++) { if(p[i]*c[i]>m) { for(int j=p[i]; j<=n; j++) dp[j]=max(dp[j],dp[j-p[i]]+w[i]); } else { int k=1; for(int j=1; c[i]>0; j<<=1) { int temp=min(j,c[i]); for(int q=n; q>=temp*p[i]; q--) dp[q]=max(dp[q],dp[q-p[i]*temp]+w[i]*temp); c[i]-=j; } } } cout<<dp[n]<<endl; } return 0; }
代码2:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=2e5+5; int a[10]; int dp[maxn]; int main() { int t=0; while(scanf("%d",&a[1])==1) { int sum=a[1]; for(int i=2; i<=6; i++) { scanf("%d",&a[i]); sum+=a[i]*i; } if(sum==0) break; if(sum%2==1) { printf("Collection #%d:\n",++t); puts("Can't be divided."); puts(""); } else { printf("Collection #%d:\n",++t); memset(dp,0,sizeof(dp)); dp[0]=1; int ans=sum/2; for(int i=1; i<=6; i++) { int n=a[i]; for(int j=1; n>0; j<<=1) { int temp=min(j,n); for(int k=ans-i*temp; k>=0; k--) if(dp[k])dp[k+i*temp]=1; n-=j; } } if(dp[ans]) puts("Can be divided.\n"); else puts("Can't be divided.\n"); } } return 0; }