1、http://acm.hdu.edu.cn/showproblem.php?pid=2844
2、此题,主要注意优化,只用二进制优化,还是超时,ac的方法是将多重背包分成完全背包和01背包,01背包中再用二进制优化,
题目大意:
Whuacmers有n中硬币,价值分别为A1,A2,A3...An ,每种硬币的个数为C1,C2,C3...Cn,要求的是从1到m,这些硬币可以凑成多少种价值,即有多少个dp[i]==i;
3、题目:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3969 Accepted Submission(s): 1578
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
8 4
4、ac代码:
#include<stdio.h> #include<string.h> #include<algorithm> int v[110]; int w[110]; int dp[100005]; using namespace std; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; memset(v,0,sizeof(v)); memset(w,0,sizeof(w)); for(int i=1;i<=100005;i++) dp[i]=-9999999; dp[0]=1; for(int i=1; i<=n; i++) scanf("%d",&v[i]); for(int i=1; i<=n; i++) scanf("%d",&w[i]); for(int i=1; i<=n; i++) { if(v[i]*w[i]>=m) { for(int j=v[i]; j<=m; j++) { dp[j]=max(dp[j],dp[j-v[i]]+v[i]); //printf("%d %d\n",j,dp[j]); } } else { for(int k=1; k<=w[i]; k=k*2) { for(int j=m; j>=v[i]*k; j--) { dp[j]=max(dp[j],dp[j-v[i]*k]+v[i]*k); } w[i]-=k; } if(w[i]>0) { for(int j=m; j>=v[i]*w[i]; j--) dp[j]=max(dp[j],dp[j-v[i]*w[i]]+v[i]*w[i]); } } } int count=0; for(int i=1; i<=m; i++) { if(dp[i]>=0) count++; } printf("%d\n",count); } return 0; }
5、只用二进制优化超时的代码:
#include<stdio.h> #include<string.h> #include<algorithm> int v[110]; int w[110]; int dp[100005]; int visit[100005]; using namespace std; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; memset(v,0,sizeof(v)); memset(w,0,sizeof(w)); memset(dp,0,sizeof(dp)); memset(visit,0,sizeof(visit)); for(int i=1;i<=n;i++) scanf("%d",&v[i]); int k=n; for(int i=1;i<=n;i++) { scanf("%d",&w[i]); for(int j=1;j<=w[i];j=j*2) { v[k++]=v[i]*j; w[i]-=j; } if(w[i]>0) { v[k++]=v[i]*w[i]; } } int count=0; for(int i=1;i<=k;i++) { for(int j=m;j>=1;j--) { if(j>=v[i]) dp[j]=max(dp[j],dp[j-v[i]]+v[i]); if(dp[j]==j&&visit[j]==0) { count++; visit[j]=1; } } } printf("%d\n",count); } return 0; } /* 3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0 */