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

被折叠的 条评论
为什么被折叠?



