题目:金明的预算方案
这是动态规划中的背包问题中的有依赖的背包问题。
幸好题目中说道:每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。否则这题就变成了一个树形DP了。
状态表达:f[i] = 当v == i时的最大价值。
状态转移方程:
f[j] = std::max(f[j],f[j-num[i].w1]+num[i].c1);
if(j-num[i].w1-num[i].w2>=0)f[j] = std::max(f[j],f[j-num[i].w1-num[i].w2]+num[i].c1+num[i].c2);
if(j-num[i].w1-num[i].w3>=0)f[j] = std::max(f[j],f[j-num[i].w1-num[i].w3]+num[i].c1+num[i].c3);
if(j-num[i].w1-num[i].w2-num[i].w3>=0)f[j] = std::max(f[j],f[j-num[i].w1-num[i].w2-num[i].w3]+num[i].c1+num[i].c2+num[i].c3);
状态数量:nv
转移代价:O(1)
时间复杂度:O(nv)
空间复杂度:O(v)
附上代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
class node
{
public:
int w1,w2,w3;
int c1,c2,c3;
}num[100];
int n,v,f[100001];
void init()
{
std::cin>>v>>n;
for(int i = 1;i<=n;i++)
{
int a,b,s;
std::cin>>a>>b>>s;
b *= a;
if(s==0)
{
num[i].w1 = a;
num[i].c1 = b;
}
else if(num[s].w2==0&&num[s].c2==0)
{
num[s].w2 = a;
num[s].c2 = b;
}
else
{
num[s].w3 = a;
num[s].c3 = b;
}
}
}
int get_ans()
{
for(int i = 1;i<=n;i++)
for(int j = v;j>=num[i].w1;j--)
{
f[j] = std::max(f[j],f[j-num[i].w1]+num[i].c1);
if(j-num[i].w1-num[i].w2>=0)f[j] = std::max(f[j],f[j-num[i].w1-num[i].w2]+num[i].c1+num[i].c2);
if(j-num[i].w1-num[i].w3>=0)f[j] = std::max(f[j],f[j-num[i].w1-num[i].w3]+num[i].c1+num[i].c3);
if(j-num[i].w1-num[i].w2-num[i].w3>=0)f[j] = std::max(f[j],f[j-num[i].w1-num[i].w2-num[i].w3]+num[i].c1+num[i].c2+num[i].c3);
}
return f[v];
}
int main()
{
init();
std::cout<<get_ans();
return 0;
}