我虽然做了好几道树形背包的题,但是一直不是十分理解,对于每一道题,总是看题解就明白,然后换一道题自己写不出来。临近NOIP,gg让我们强化一下背包以及树形背包,我也恰有此打算,于是又开始从头学习了树形背包。

看了好多博客以及论文之后,对树形背包确实有了一个全新的认识,尤其是这篇博客以及徐持恒的论文《浅谈积累背包问题》,对我有很大的帮助。两者都提到了泛化物品(当然这个名词最初是在背包九讲里面提到的)这个概念,我觉得这是对树形背包O(n * v2)做法的一种不同理解,不过我认为引入这个名词的主要目的还是对O(nv)的做法做出了解释。遗憾的是,我虽然用O(nv)的做法成功写出了一道题,然而却仍旧不是很懂。所以这篇博文主要是讲解O(n * v2)的做法,也算是整理自己的学习笔记吧。

如果哪一天我把O(nv)的做法看懂了的话,可能还会来更这篇博客。

上文已经提到,对于O(n * v2)的做法有两种不同的理解,那么我在这里就分别阐述一下。

都以这道题为例

一、用分组背包来理解

首先题中给的依赖关系是一个森林,那么可以建立一个虚拟节点0,作为森林的根,形成一棵树。

令dp[u][j]表示以 u 为根的子树中,选 j 门课(体积)能得到的最大学分。那么 u 一定要选(初始化dp[u][1] = val[u]),而对于子树内其他点的选取情况,可以把每一种选取方案看成一个物品,又因为每一种方案都是互斥的,每一组只能选一个,那么就是一个分组背包了。这里的组数,是 u 的儿子个数 p = |son(u)|,对于一个vi ∈son(u),他其实代表了j - 1个物品(因为还要选u),拿其中一个为例,dp[vi][k](0 <= k < j)这种选取方案才代表一个物品。

现在考虑转移方程。按照分组背包的写法,我们应该先加一维,dp[u][k][j]表示以x为根的子树,选到第k组,选了 j 门课得到的最大学分。于是有dp[u][k][j] = max(dp[u][k - 1][j], dp[u][k - 1][j - h] + dp[v][sz][h])。注意,dp[v][sz][h]代表一个物品,sz是v的所有组数,因为要保证最优,所以一定从v的所有组数选完的状态转移到u。

然后再模仿分组背包省去第二维,把 j 倒着枚举。

核心代码:

 1 void dfs(int now)
 2 {
 3   for(int i = head[now]; i; i = e[i].nxt)
 4     {
 5       dfs(e[i].to);
 6       for(int j = m + 1; j; --j)
 7     for(int k = 0; k < j; ++k) //这一维正着倒着都行,有很多书上是倒着的
 8       dp[now][j] = max(dp[now][j], dp[now][j - k] + dp[e[i].to][k]);
 9     }
10 }

对于每一个节点只会进行一次O(v2)的分组背包,所以复杂度O(n * v2)。

二、用泛化物品来理解

首先得解释一下啥叫泛化物品:一个价值随体积改变而改变的物品,而且对于一个体积 i,有对应的v[i]。

这个其实人人都见过,只不过没有听说这个名词而已。比如求解01背包就是泛化一个物品的过程,得到的dp[i]就是一个泛化物品。

还有这么回事,泛化物品的和 :有两个泛化物品G1[i], G2[i],要将这两个物品合并。做法就是对于每一个体积 i ,枚举分配给这两个物品的体积 j ,G[i] = max{G1[j], G2[i - j]}。复杂度O(v2)。

现在用泛化物品的概念看看树形背包。dp[u][j]表示的是u所在的泛化物品,则从子树向上递归的时候,其实就是不断地将u所在的泛化物品和他的子树vi的泛化物品合并。合并一次的复杂度O(v2),一共n各节点,每合并一次减少一个,所以总复杂度还是O(n * v2)。

代码和上面完全相同,因为这本来就是对树形背包的两种理解,而不是两种写法。

 1 void dfs(int now)
 2 {
 3   for(int i = head[now]; i; i = e[i].nxt)
 4     {
 5       dfs(e[i].to);
 6       for(int j = m + 1; j; --j)
 7     //倒着枚举,因为左边的dp[now][j]代表新的物品,右边的dp[now][j]是原来的物品
 8     for(int k = 0; k < j; ++k) //枚举分配体积
 9       dp[now][j] = max(dp[now][j], dp[now][j - k] + dp[e[i].to][k]);
10     }
11 }

树形背包O(n * v2)的做法到此也基本讲完了,但这其实都是基础,深入的话还是得靠自己刷题去“悟”。还有一点就是如果哪位大佬会O(nv)的做法,能不能给我讲讲……

转载于:https://www.cnblogs.com/mrclr/p/9894039.html

树形背包O(n * v^2)入门相关推荐

  1. 【每日DP】day 8、P2014 [CTSC1997]选课(树形DP(树形背包)模板)难度⭐⭐⭐

    P2014 [CTSC1997]选课 题意为选一门课前要看它是否有前提条件:即选了一门主课才能选 "副科",所以可以树形背包来做. 注意是不能用分组背包来做,因为这道题附件有很多个 ...

  2. [HAOI2015]树上染色(树形dp,树形背包)

    链接:https://ac.nowcoder.com/acm/problem/19996 来源:牛客网 题目描述 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个 ...

  3. *多叉树的树形背包常见建模方法

    一.多叉树变二叉树. 这个技巧其实也有两种具体的方法:树的孩子兄弟表示法与dfs序法. 1.树的孩子兄弟表示法. 大家在学习树形结构时一定接触了一个多叉树变二叉树的方法,就是把每个点与它的第一个儿子连 ...

  4. 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp

    题目描述 给你一棵 $n$ 层的完全二叉树,每个节点可以染黑白两种颜色.对于每个叶子节点及其某个祖先节点,如果它们均为黑色则有一个贡献值,如果均为白色则有另一个贡献值.要求黑色的叶子节点数目不超过 $ ...

  5. [HAOI2015]树上染色(树形背包)

    有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之间的距离加 ...

  6. 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp

    题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...

  7. 【bzoj5072】[Lydsy十月月赛]小A的树 树形背包dp

    题目描述 给出一棵n个点的树,每个点有黑白两种颜色.q次询问,每次询问给出x和y,问能否选出一个x个点的联通子图,使得其中黑点数目为y. 输入 第一行一个正整数 T 表示数据组数. 对于每一组数据,第 ...

  8. HDU 4276 The Ghost Blows Light 最短路+树形背包

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4276 目录 题意 分析 Code 题意 有一棵树,每个节点都有财富wi,每条边都会花费ci的时间,问你 ...

  9. [Jsoi2016]最佳团体 BZOJ4753 01分数规划+树形背包/dfs序

    分析: 化简一下我们可以发现,suma*ans=sumb,那么我们考虑二分ans,之后做树形背包上做剪枝. 时间复杂度证明,By GXZlegend O(nklogans) 附上代码: #includ ...

  10. P4322-[JSOI2016]最佳团体【0/1分数规划,树形背包】

    正题 题目链接:https://www.luogu.com.cn/problem/P4322 题目大意 nnn个点的一棵树,每个节点有一个(si,pi)(s_i,p_i)(si​,pi​),选择一个点 ...

最新文章

  1. 四位专家谈:数字医学中的因果关系
  2. python的一些常用操作
  3. Visio中插入mathtype公式,解决直线交叉弯曲的问题
  4. Jar文件的小小总结(原创)
  5. 通过相似性或相异指数的数值分布比较群落Beta多样性高低
  6. ssm使用全注解实现增删改查案例——Dept
  7. 分析启动耗时 android,Android app启动耗时分析
  8. Anaconda Python3.6 OpenCV4.1.0 Ubuntu 16.04源码编译
  9. FISCO BCOS (六)———ubantu安装mysql5.7
  10. BZOJ3083: 遥远的国度
  11. CPT203-Software Engineering
  12. rpc error: code = Unimplemented desc =
  13. 我喜欢的学科计算机 英文作文,我喜欢的学科写英语作文40字
  14. FFMPEG直播推流
  15. MATLAB实现分支定界法求解整数规划
  16. 军队文职(数学2+物理)——高等数学 3、求极限(一)
  17. TH-OCR文字识别SDK 12.X介绍
  18. 按键精灵mysql_mysql,按键精灵,读取写入
  19. C-V2X业务演进白皮书
  20. 电影演员合作关系可视化(一)整体思路与爬虫编写

热门文章

  1. Spring整合MyBatis原理之Mapper接口代理对象的产生以及调用 (三)
  2. session的生命周期是怎样的
  3. 在Linux环境下select函数的初体验
  4. 所有浏览器的 CSS selectors 兼容性
  5. Ubuntu下PostgreSQL数据库集群(PL/Proxy)配置方法
  6. JAVA 基础语法——开发环境以及J2SE代码实现
  7. 使用cardview和recycleview时碰到的一些问题
  8. [UESTC SC T1] 最大疯子树
  9. nodejs后台系列--第四篇--koa(二)
  10. vue项目中打包的相关配置问题