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

本文解析了完全背包和多重背包问题,并提供了具体的实现代码示例。详细介绍了如何通过改变遍历顺序来区分01背包与完全背包,以及如何将多重背包转换为01背包问题求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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,当然需要倒序了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值