HDU3449 Consumer 变种背包,还是背包

来源:互联网 发布:华为java面试题及答案 编辑:程序博客网 时间:2024/06/05 04:57

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;}


原创粉丝点击