您的位置:首页 > 其它

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

2014-10-09 09:18 281 查看
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;
				}
				else
					break;
			}
		}
然后按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;
				}
				else
					break;
				count++;
			}
		}
注意count++在最后失效,影响了作为统计数量的作用。

另外强调一下,弄清楚正序和倒序。倒序是01,正序是完全。多重背包转换成01,当然需要倒序了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: