题意:
n个游戏机,有w钱
每个游戏机上有游戏,每个游戏有价格和娱乐值,游戏机有价格,没有娱乐值,玩游戏必须要用对应的游戏机,问娱乐值最大是多少
题解:
有依赖关系的背包问题
对于一个游戏机,游戏机本身没有娱乐值,但是上面的游戏有娱乐值,所以我们可以选择不要这个游戏机,或者要游戏机以及里面的物品,我们要求出选择这个箱子以及其中的物品在各个费用下所能取的最大价值
dp[i][j]就表示前i个游戏机,花费在j以内的最大价值
如果j<游戏机价格,说明连游戏机都买不起,更别想游戏,所以dp[i][j]=-1;
如果j>游戏机价格val,j中val用于买游戏机,此时的状态等于不选第i个游戏机,有j-val钱的状态dp[i][j]=dp[i-1][j-val]
现在的dp[][]表示选了游戏机后的状态,直接对游戏机中的游戏进行01背包求各个费用下的最大价值
if(dp[i][j-cost]!=-1)
dp[i][j] = max(dp[i][j], dp[i][j - cost] + val);
经过上述操作,我们得到了选择当前游戏机i 的的情况下,各个费用下的最大价值
然后我们去和不选这个游戏机的情况下,各个费用下的最大价值取最大值,这样就得到挑选过游戏机i后得到的各个费用的最大值
不选游戏机就是dp[i-1][…]
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
//#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int Max = 1e5 + 10;
int n, m;
ll dp[55][Max];
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
memset(dp, 0, sizeof(dp)); //初始化
for(int i = 1 ;i <= n;i ++)
{
int box, num;
scanf("%d%d", &box, &num);
for (int j = 0;j < box; j++) //总费用小于box,无法买任何物品
dp[i][j] = -1;
for (int j = box;j <= m; j++) //由前一个状态j-box,选择了当前的游戏机后转移而来
dp[i][j] = dp[i - 1][j - box];
//上述表示选择了当前的游戏机后的价值(没有和不选进行比较)
for(int k = 0 ;k < num ; k ++) //由01背包从选择了箱子的状态转移到其余状态
{
int cost;ll val;
scanf("%d%lld", &cost, &val);
for(int j = m ; j >= cost ;j --)
{
if(dp[i][j-cost] != -1)
{
dp[i][j] = max(dp[i][j], dp[i][j - cost] + val);
}
}
}
for (int j = 0;j <= m;j++) //和不选择此盒子作比较
dp[i][j] = max(dp[i][j], dp[i - 1][j]);
}
printf("%lld\n", dp[n][m]);
}
return 0;
}