https://www.luogu.com.cn/problem/P1064
题意:
有n元m件物品,每个物品价值v重要度w和附件p,若p=0说明这是主件,p>0则p表示该物品为附件,p是所属主件的编号。附件必须和主件一起买。
思路:
和01背包很像,只不过多了附件。附件必须和主件一起购买,我们可以把它们绑起来,遍历主件,若主件有附件则再去判断附件。(有点像hash里拉链法的存储结构,只不过这里用数组来模拟,指针写起来太麻烦)
代码:
#include <bits/stdc++.h>
using namespace std;
int fu[100][2],f[40000];//fu[i][]记录第i件的附件有哪些
int v[100],w[100],p[100];
int main()
{
int n,m;
cin>>n>>m;
int x,y,z;
int cnt=0;
for(int i=1;i<=m;i++)
{
cin>>v[i]>>w[i]>>p[i];
w[i]*=v[i];
if(p[i])//如果是附件则记录
{
if(!fu[p[i]][0])//第一件
fu[p[i]][0]=i;
else
fu[p[i]][1]=i;
}
}
for(int i=1;i<=m;i++)
{
if(!p[i])//不是附件
for(int j=n;j>=0;j--)
{
if(j>=v[i])
{
f[j]=max(f[j],f[j-v[i]]+w[i]);
if(fu[i][0])//如果有附件
{
int t1=fu[i][0];
int t2=fu[i][1];//若无附件,则t2为零,不影响结果
if(j-v[i]-v[t1]>=0)//可以买主件和附件1
f[j]=max(f[j],f[j-v[i]-v[t1]]+w[i]+w[t1]);
if(j-v[i]-v[t2]>=0)//可以买主件和附件2
f[j]=max(f[j],f[j-v[i]-v[t2]]+w[i]+w[t2]);
if(j-v[i]-v[t1]-v[t2]>=0)//可以买主件和附件1、2;
f[j]=max(f[j],f[j-v[i]-v[t1]-v[t2]]+w[i]+w[t1]+w[t2]);
}
}
}
}
cout<<f[n];
return 0;
}