我们把附件和它的主件归到一组,其中主件为每组第一项编号为0。因为每组最多两个附件,对于每一组,决策有以下五种(假定存在两个附件):
1.不取这组
2.只取主件
3.取主件和附件1
4.取主件和附件2
5.取主件和附件1附件2
设
F
[
i
,
j
]
F[i,j]
F[i,j] 表示考虑到第
i
i
i 组容量为
j
j
j 时的最大价值
状态转移方程(假定存在两个附件)
F
[
i
,
j
]
=
max
{
F
[
i
−
1
,
j
]
F
[
i
−
1
,
j
−
v
[
i
]
[
0
]
]
+
v
[
i
]
[
0
]
×
p
[
i
]
[
0
]
F
[
i
−
1
,
j
−
v
[
i
]
[
0
]
−
v
[
i
]
[
1
]
]
+
v
[
i
]
[
0
]
×
p
[
i
]
[
0
]
+
v
[
i
]
[
1
]
×
p
[
i
]
[
1
]
F
[
i
−
1
,
j
−
v
[
i
]
[
0
]
−
v
[
i
]
[
2
]
]
+
v
[
i
]
[
0
]
×
p
[
i
]
[
0
]
+
v
[
i
]
[
2
]
×
p
[
i
]
[
2
]
F
[
i
−
1
,
j
−
v
[
i
]
[
0
]
−
v
[
i
]
[
1
]
−
v
[
i
]
[
2
]
]
+
v
[
i
]
[
0
]
×
p
[
i
]
[
0
]
+
v
[
i
]
[
1
]
×
p
[
i
]
[
1
]
+
v
[
i
]
[
2
]
×
p
[
i
]
[
2
]
F[i,j]=\max\begin{cases}F[i-1,j]\\F[i-1,j-v[i][0]]+v[i][0]\times p[i][0]\\F[i-1,j-v[i][0]-v[i][1]]+v[i][0]\times p[i][0]+v[i][1]\times p[i][1]\\F[i-1,j-v[i][0]-v[i][2]]+v[i][0]\times p[i][0]+v[i][2]\times p[i][2]\\F[i-1,j-v[i][0]-v[i][1]-v[i][2]]+v[i][0]\times p[i][0]+v[i][1]\times p[i][1]+v[i][2]\times p[i][2]\end{cases}
F[i,j]=max⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧F[i−1,j]F[i−1,j−v[i][0]]+v[i][0]×p[i][0]F[i−1,j−v[i][0]−v[i][1]]+v[i][0]×p[i][0]+v[i][1]×p[i][1]F[i−1,j−v[i][0]−v[i][2]]+v[i][0]×p[i][0]+v[i][2]×p[i][2]F[i−1,j−v[i][0]−v[i][1]−v[i][2]]+v[i][0]×p[i][0]+v[i][1]×p[i][1]+v[i][2]×p[i][2]
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n,m,v[61],p[61],w[61],tot,q[61],gro[61],f[32001];
vector<int>g[61];
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&v[i],&p[i],&q[i]),w[i]=v[i]*p[i];
for(int i=1;i<=m;i++)
if(q[i]==0)g[++tot].push_back(i),gro[i]=tot;
for(int i=1;i<=m;i++)
if(q[i]>0)g[gro[q[i]]].push_back(i);
for(int i=1;i<=tot;i++)
for(int j=n;j>=0;j--)
{
if(j>=v[g[i][0]])f[j]=max(f[j],f[j-v[g[i][0]]]+w[g[i][0]]);
if(g[i].size()>=2&&j>=v[g[i][0]]+v[g[i][1]])f[j]=max(f[j],f[j-v[g[i][0]]-v[g[i][1]]]+w[g[i][0]]+w[g[i][1]]);
if(g[i].size()>=3)
{
if(j>=v[g[i][0]]+v[g[i][1]]+v[g[i][2]])f[j]=max(f[j],f[j-v[g[i][0]]-v[g[i][1]]-v[g[i][2]]]+w[g[i][0]]+w[g[i][1]]+w[g[i][2]]);
if(j>=v[g[i][0]]+v[g[i][2]])f[j]=max(f[j],f[j-v[g[i][0]]-v[g[i][2]]]+w[g[i][0]]+w[g[i][2]]);
}
}
printf("%d\n",f[n]);
return 0;
}
总结
一道典型的有依赖的背包问题,要学会如何处理这类问题。