poj 3624 Charm Bracelet (01背包 水题)
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int dp[1600005]; int v[3500],w[3500]; int max(int a,int b) { return a>b?a:b; } int main() { int n,vv; while(scanf("%d%d",&n,&vv)!=EOF) { for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { for(int j=vv;j>=v[i];j--) dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } printf("%d\n",dp[vv]); } return 0; }
hdu 1864 最大报销额 (01背包)
由于数组下标不能是double 型,所以把所有的报销费用扩大一百倍进行递推。
值得吐糟的是:数组要开到3*10^7那么大,题目给的是每张报销额度不超过1000,发票最多30张,按理
dp[]开到30*1000+10就够了,我本来出于保险还扩大了10倍,还是re。。。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int dp[3000010]; //数组一定要开这么大,否则RE int v[31]; int main() { int n,m,flag,r; char t; double tmp,s1,s2,s3,a,sum; while(scanf("%lf%d",&sum,&n)!=EOF) { if(n==0)break; flag=0;r=0; for(int i=1;i<=n;i++) { s1=s2=s3=0; scanf("%d",&m); for(int j=1;j<=m;j++) { scanf(" %c:%lf",&t,&a); if(t!=‘A‘&& t!=‘B‘&&t!=‘C‘) flag=1; if(t==‘A‘) s1+=a; else if(t==‘B‘) s2+=a; else s3+=a; } if(!flag) { tmp=s1+s2+s3; if(s1>600 || s2>600 ||s3>600||tmp>1000) continue; v[r++]=tmp*100; } else flag=0; } memset(dp,0,sizeof(dp)); for(int i=0;i<r;i++) { for(int j=sum*100;j>=v[i];j--) dp[j]=max(dp[j],dp[j-v[i]]+v[i]); } int ans=sum*100; printf("%.2lf\n",dp[ans]*1.0/100); } return 0; }
hdu 1171 Big Event in HDU (多重背包)
直接按《背包九讲》的模板写就可以了。
吐糟:我为什么每次都要把二进制优化 的位运算移位方向弄反= =诶。。。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define INF 0xffffff using namespace std; int v[55],c[55]; int p[5000],dp[500010]; int main() { int n,sum,tmp,r,u; while(scanf("%d",&n)!=EOF) { if(n<0) break; sum=0; for(int i=1;i<=n;i++) { scanf("%d%d",&v[i],&c[i]); sum+=v[i]*c[i]; } u=sum/2; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { if(v[i]*c[i]>u) { for(int j=v[i];j<=u;j++) { dp[j]=max(dp[j],dp[j-v[i]]+v[i]); } } else { tmp=1;r=0; while(tmp<c[i]) { p[r++]=tmp*v[i]; c[i]-=tmp; tmp<<=1; } if(c[i]) p[r++]=c[i]*v[i]; for(int k=0;k<r;k++) { for(int j=u;j>=p[k];j--) { dp[j]=max(dp[j],dp[j-p[k]]+p[k]); } } } } printf("%d %d\n",sum-dp[u],dp[u]); } return 0; }
hdu 2602 Bone Collector (01背包)
没什么好说的。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int v[1010],w[1010]; int dp[1010]; int main() { int T,n,vv; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&vv); for(int i=0;i<n;i++) scanf("%d",&w[i]); for(int i=0;i<n;i++) scanf("%d",&v[i]); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) { for(int j=vv;j>=v[i];j--) { dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } } printf("%d\n",dp[vv]); } return 0; }