HDU3449 Consumer 变种背包,还是背包

本文深入探讨了一种背包问题的变种,详细解释了如何通过设定两个数组来解决此类问题,确保正确地计算出最优解。文章强调了在解决过程中避免错误地重复购买物品的重要性,并提供了实现这一解决方案的代码示例。

Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=3449


【思路】


这道变种的背包其实不是很难理解。

对于一个箱子,有买和不买的区别,要注意的是买了箱子的话是要花费钱的。

所以要设定两个数组。

一个是记录到当前箱子之前的最值,另一个是记录当前箱子所花费的最值。

当前箱子必须从之前的箱子加上箱子的花费得来。

所以设定的第二个数组记录的都是在买了箱子的前提下的最值。

最后逐步合并两个箱子的最值,即可得到结果。

如果只利用一个数组,那么转移的时候可能是在之前买了箱子的基础上得到的,所以会多买了箱子,这是不正确的。


【代码】


#include <iostream>
using namespace std;

const int maxn = 100000;

int dp[2][maxn+5];//dp[0]用于记录之前的状态,dp[1]用于记录买了某个箱子之后的状态

int main()
{
	int n, w, p, m, c, v;
	int i, j, k;
	while(scanf("%d %d", &n, &w)!=EOF)
	{
		memset(dp, 0, sizeof(dp));
		for (i=0; i<n; i++)
		{
			scanf("%d %d", &p, &m);
			for (j=p; j<=w; j++)
				dp[1][j] = dp[0][j-p];//当前箱子必定从之前状态加上箱子花费得来
			for (j=0; j<m; j++)//对当前箱子在dp[1]上进行普通的01背包
			{
				scanf("%d %d", &c, &v);
				for (k=w-c; k>=p; k--)
				{
					if (dp[1][k]+v>dp[1][k+c])
						dp[1][k+c] = dp[1][k]+v;
				}
			}
			for (j=p; j<=w; j++)//合并两个数组
			{
				if (dp[1][j]>dp[0][j])
					dp[0][j] = dp[1][j];
			}
		}
		printf("%d\n", dp[0][w]);
	}
	return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值