九度OJ-1454,1455-Piggy-Bank,珍惜现在,感恩生活

来源:互联网 发布:.net与java的区别 编辑:程序博客网 时间:2024/04/28 18:55

http://ac.jobdu.com/problem.php?pid=1454

http://ac.jobdu.com/problem.php?pid=1455

这里想对背包问题做一个小总结。1454即完全背包问题,即某个“物品”可以取无限次,其次,背包需要正好装满。

背包正好装满的解决方式,只是改变初始值,而物品可以“无限次取”,是将01背包倒序改变dp[j]变为正序。如下:

for(j=1;j<=weight;j++){dp[j]=INT_MAX;}
for(i=1;i<=n;i++){for(j=coin[i].w;j<=weight;j++){if(dp[j-coin[i].w]!=INT_MAX)dp[j]=min(dp[j-coin[i].w]+coin[i].v,dp[j]);}}
1455是多重背包,每种物品最多可以选ki次,可以将其变成ki个物品,或者log2ki个物品。如下:

ki:

for(i=0;i<kind;i++){scanf("%d%d%d",&p,&h,&c);while(c--){dami[count].w=p;dami[count].v=h;count++;}}
log2ki:

for(i=1;i<=n;i++){scanf("%d%d%d",&p,&h,&c);k=1;while(1){//dami[count].v=h*k;dami[count].w=p*k;count++;c-=k;if(c>=k*2){k*=2;}else if(c>0){k=c;}elsebreak;}}
然后按01背包处理即可。

log2ki方式我犯过一个错误:

for(i=1;i<=n;i++){scanf("%d%d%d",&p,&h,&c);k=1;while(1){//dami[count].v=h*k;dami[count].w=p*k;c-=k;if(c>=k*2){k*=2;}else if(c>0){k=c;}elsebreak;count++;}}
注意count++在最后失效,影响了作为统计数量的作用。

另外强调一下,弄清楚正序和倒序。倒序是01,正序是完全。多重背包转换成01,当然需要倒序了。




0 0