我是靠谱客的博主 笨笨果汁,最近开发中收集的这篇文章主要介绍树型分组背包(模板题),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

感觉还是非常巧妙地

光说理论不好讲,拿道题目来说P1273 有线电视网

这 道 题 很 难 想 这道题很难想

但 是 如 果 把 每 棵 子 树 当 成 一 个 组 , 那 么 组 内 可 以 不 选 叶 子 节 点 但是如果把每棵子树当成一个组,那么组内可以不选叶子节点 ,

选 1 个 叶 子 节 点 , 2 个 叶 子 节 点 . . . . . . . 选1个叶子节点,2个叶子节点....... 1,2.......

而一个组中最多只能有一种决策,这不就是分组背包吗?

回 忆 一 下 普 通 的 分 组 背 包 转 移 color{Red}回忆一下普通的分组背包转移

for(每一组物品)
for(背包的容量)
for(当前这组选哪些物品)
开始dp

那 我 们 效 仿 这 个 , 定 义 状 态 d p [ i ] [ u ] [ j ] 的 含 义 为 那我们效仿这个,定义状态dp[i][u][j]的含义为 仿,dp[i][u][j]

在 u 为 根 的 子 树 中 , 在 前 i 个 儿 子 中 选 择 j 个 叶 子 节 点 的 最 大 收 益 在u为根的子树中,在前i个儿子中选择j个叶子节点的最大收益 u,ij

其中儿子代表每组物品,要选的叶子节点数是容量,当前儿子选几个叶子节点是这组要选哪些物品

然 后 的 话 把 背 包 容 量 倒 序 枚 举 可 以 优 化 掉 一 维 然后的话把背包容量倒序枚举可以优化掉一维

#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;
}
}
}

最后

以上就是笨笨果汁为你收集整理的树型分组背包(模板题)的全部内容,希望文章能够帮你解决树型分组背包(模板题)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(84)

评论列表共有 0 条评论

立即
投稿
返回
顶部