博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[算法模版]树形背包
阅读量:5263 次
发布时间:2019-06-14

本文共 853 字,大约阅读时间需要 2 分钟。

[算法模版]树形背包

树形01背包

树形01背包和普通背包不同点在于物品之间有相互的依赖关系。选取儿子物品的必要条件是选取了所有他的祖先。

我们考虑使用dp[i][j]代表第i个点的子树内,花费了j个容量能得到的最大权值。

伪代码:

for(int i=1;i<=son;i++){//枚举所有儿子  dfs(son[i]);//先处理儿子  for(int j1=m;j1>=0;j1--){//枚举当前点用掉了多少容量(正着枚举会变成完全背包)    for(int j2=0;j2<=j1;j2++){//枚举这个儿子分配多少      dp[i][j1]=max(dp[i][j1],dp[i][j1-j2]+dp[son[i]][j2]);//更新状态    }  }}

显然,复杂度是\(O(n*m^2)\)的。

特殊情况的树形背包优化

当物品的体积全部为1时,我们可以把它优化到\(O(n^2)\)的复杂度。

来自lsj爷爷的代码:

1669439-20190917170234879-1322523546.png

乍一看根原来的没什么不同,但是需要注意,对于每一对点,都只会在他们的LCA被枚举到一次。可以自己想想为什么。

复杂度\(n^2\)

树形01背包优化

有一种方法可以把它优化到\(n*m\)的复杂度。

在这种dp方法中,dp[i][j]是指在点i及其所有祖先必须选,dfs序小于ii子树内的可以选,对于容量为j的背包,最大权值是多少。

所以代码也很简单:

void dfs(int now,int fa){    for(int i=w[now];i<=m;i++){        dp[now][i]=dp[fa][i-w[now]]+v[now];    }     for(int i=0;i

注意,必须把所有不可行的方案置为-1e9,否则虽然这种方案答案是0,但是它的儿子可能在这种不成立的状态基础上转移出一个答案很大的状态。

参考资料

转载于:https://www.cnblogs.com/GavinZheng/p/11519540.html

你可能感兴趣的文章
Web 安全入门-书籍及建议
查看>>
ArcIMS地图配置文件,地图服务,请求和响应之间的关系(转)
查看>>
jenkins 使用的python 不是指定的python 的解决方法
查看>>
修复公路
查看>>
【SAS NOTE】“:”&时间处理
查看>>
3-6局部变量的存储方式 & 3-7字符型字面值
查看>>
sgu 110 Dungeon
查看>>
Linux下关于进程的一些操作
查看>>
Hibernate学习(七)
查看>>
prim算法基础详解(无向赋权图的最小生成树MST)
查看>>
vijos1404 遭遇战
查看>>
Androidstudio创建项目jdk版本问题
查看>>
《般若波罗蜜多心经》全文及解释
查看>>
数字类型内置方法
查看>>
[转载]使用Openfiler构建ESXI网络共享存储iSCSI
查看>>
Android基于mAppWidget实现手绘地图(十四)–在一个应用中使用多个地图
查看>>
iOS开发核心动画之粒子效果
查看>>
实验1 查看CPU和内存,用机器指令和汇编指令编程
查看>>
Beta 冲刺(1/7)
查看>>
算法之经典排序-冒泡排序(bubble sort)
查看>>