有依赖背包问题详解参考背包九讲:blog.csdn.net/yandaoqiush…
HDU 3449 Consumer:acm.hdu.edu.cn/showproblem…
luogu P1064 金明的预算方案:www.luogu.org/problem/P10…
HDU 3449:
先来看HDU 3449这题,是基本的有依赖背包问题,这题的输入已经帮我们把物品按组划分好了,不用我们自己分,所以直接套模板。开个二维dp[i][j]数组,i是背包序号,j是当前花费的金额,先对每一组单独处理:
1. 买当前组的主物的情况:
- 金额不到主物的价格的dp设为-1,表示不可达,达到主物价格的设为上一层当前金额+主物的价值
- 对组内物品是简单的01背包
#include<iostream>
#include<fstream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[51][100001] = {0};
int main(void)
{
int n, w, pi, mi;
while(cin >> n >> w)
{
for(int i = 1; i <= n; i++) //对每个箱子单独做处理
{
cin >> pi >> mi;
//假设买该箱子的情况
//钱不够买箱子
for(int j = 0; j < pi; j++)
dp[i][j] = -1;
//钱足够买箱子, 花费j元的最大价值, 箱子价值为0
for(int j = pi; j <= w; j++)
dp[i][j] = dp[i-1][j-pi] + 0;
int c[11] = {0};
int v[11] = {0};
for(int k = 1; k <= mi; k++){
cin >> c[k] >> v[k];
for(int j = w; j >= c[k]; j--)
if(dp[i][j - c[k]] != -1)
dp[i][j] = max(dp[i][j], dp[i][j-c[k]] + v[k]);
}
//不买该箱子的情况
for(int j = w; j >= 0; j--)
dp[i][j] = max(dp[i][j], dp[i-1][j]);
}
cout << dp[n][w] << endl;
}
return 0;
}Luogu P1064:
这题的问题就在于题目的输入没有帮我们直接分好组,所以我一开始想直接用数组做,但是很麻烦,得找到每一个物品对应的组,状态方程也不好写。所以我改写成结构体形式,虽然表达式麻烦些,但是思路清楚了许多。和上一题还有一点不同,就是每一组的主物是由价值的,而不是+0。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<fstream>
#include<cstring>
using namespace std;
struct Second{
int price;
int weight;
};
struct Bag{
Second second[61];
int bag_no;
int secondNum = 0;
int bag_price;
int bag_weight;
} bag[61];
int dp[61][32001];
int main(void)
{
int N, m;
cin >> N >> m;
memset(bag, 0, sizeof(bag));
memset(dp, 0, sizeof(dp));
int bag_num = 1;
for(int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
if(c == 0){ //Input is a bag
bag[bag_num].bag_no = i;
bag[bag_num].bag_price = a;
bag[bag_num].bag_weight = b;
bag_num++;
}
else{ //Input is a second
for(int temp = 1; temp <= bag_num; temp++){
if(bag[temp].bag_no == c){
bag[temp].secondNum++;
bag[temp].second[bag[temp].secondNum].price = a;
bag[temp].second[bag[temp].secondNum].weight = b;
}
}
}
}
for(int i = 1; i <= bag_num; i++)
{
//假设买该主物品
for(int j = 0; j < bag[i].bag_price; j++) dp[i][j] = -1;
for(int j = bag[i].bag_price; j <= N; j++) dp[i][j] = dp[i-1][j-bag[i].bag_price] + bag[i].bag_price * bag[i].bag_weight;
for(int j = 1; j <= bag[i].secondNum; j++)
for(int k = N; k >= bag[i].second[j].price; k--)
if(dp[i][k - bag[i].second[j].price] != -1)
dp[i][k] = max(dp[i][k], dp[i][k - bag[i].second[j].price] + bag[i].second[j].price * bag[i].second[j].weight);
//比较买该主物和不买哪个dp高
for(int j = 0; j <= N; j++)
dp[i][j] = max(dp[i][j], dp[i-1][j]);
}
cout << dp[bag_num][N] << endl;
}