感觉还是非常巧妙地
光说理论不好讲,拿道题目来说P1273 有线电视网
而一个组中最多只能有一种决策,这不就是分组背包吗?
for(每一组物品)
for(背包的容量)
for(当前这组选哪些物品)
开始dp
其中儿子代表每组物品,要选的叶子节点数是容量,当前儿子选几个叶子节点是这组要选哪些物品
#include <bits/stdc++.h>
using namespace std;
const int maxn=3009;
int n,m,dp[maxn][maxn],w[maxn];
struct p{
int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w){
d[cnt]=(p){ v,head[u],w},head[u]=cnt++;
}
int dfs(int u)
{
dp[u][0]=0;
if( u>n-m )
{
dp[u][1]=w[u];
return 1;
}
int leaf=0;
for(int i=head[u];i;i=d[i].nxt)
{
int v=d[i].to;
int t=dfs(v);
leaf+=t;
for(int j=leaf;j>0;j--)//一共选几个叶子节点
{
for(int q=0;q<=j&&q<=t;q++)
dp[u][j]=max(dp[u][j],dp[v][q]+dp[u][j-q]-d[i].w);
}
}
return leaf;
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n-m;i++)
{
int s; cin >> s;
for(int j=1;j<=s;j++)
{
int r,w;
cin >> r >> w;
add(i,r,w);
}
}
for(int i=0;i<=3000;i++)
for(int j=0;j<=3000;j++)
dp[i][j]=-999999999;
for(int i=n-m+1;i<=n;i++) cin >> w[i];
dfs(1);
for(int j=m;j>=0;j--)
{
if(dp[1][j]>=0)
{
cout<<j;
return 0;
}
}
}