我虽然做了好几道树形背包的题,但是一直不是十分理解,对于每一道题,总是看题解就明白,然后换一道题自己写不出来。临近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 倒着枚举。

核心代码:

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

对于每一个节点只会进行一次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)。

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

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

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

树形背包O(n * v^2)入门的更多相关文章

  1. poj 1155 TELE (树形背包dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接: poj-1155 题意 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构, ...

  2. poj2486Apple Tree[树形背包!!!]

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9989   Accepted: 3324 Descri ...

  3. cdoj 1136 邱老师玩游戏 树形背包

    邱老师玩游戏 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1136 Desc ...

  4. HDU 1011 树形背包(DP) Starship Troopers

    题目链接:  HDU 1011 树形背包(DP) Starship Troopers 题意:  地图中有一些房间, 每个房间有一定的bugs和得到brains的可能性值, 一个人带领m支军队从入口(房 ...

  5. bzoj 4813: [Cqoi2017]小Q的棋盘 [树形背包dp]

    4813: [Cqoi2017]小Q的棋盘 题意: 某poj弱化版?树形背包 据说还可以贪心... #include <iostream> #include <cstdio> ...

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

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

  7. Luogu 1273 有线电视网 - 树形背包

    Description 树形背包, 遍历到一个节点, 枚举它的每个子节点要选择多少个用户进行转移. Code #include<cstring> #include<cstdio> ...

  8. BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包

    分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...

  9. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜

    传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...

随机推荐

  1. NOI 2018 酱油记

    转眼离 NOI 2018 已经过了一个星期了,退役的我还是随便来水水吧. 语法.错字之类的可能会很多,但是我也不拘这点小节了. 恭喜 yww, zjt, sk 进队,zwl, myh au , yay ...

  2. ngnix优化【转】

    nginx的优化 1. gzip压缩优化 2. expires缓存有还 3. 网络IO事件模型优化 4. 隐藏软件名称和版本号 5. 防盗链优化 6. 禁止恶意域名解析 7. 禁止通过IP地址访问网站 ...

  3. Python下ImportError: DLL load failed: 找不到指定的模块

    环境:Anaconda3 Python3.7 scarpy1.5 版本似乎都能对的上.但是在cmd下报错 如下截图. 从以上错误来看,应该是lxml包有异常. pip uninstall lxml包. ...

  4. [javaEE] 开源数据库连接池

    一些开源组织提供了数据源的独立实现: DBCP数据库连接池 C3P0数据库连接池 Apache Tomcat内置的连接池 DBCP连接池 apache提供的连接池实现,需要导入common-dbcp. ...

  5. CentOS 启动-运行级别

    Linux系统的启动过程:内核的引导 > 运行init > 系统初始化 > 建立终端 > 用户登录系统 运行init init 进程是系统所有进程的起点: 主要功能: 准备软件 ...

  6. Java基础(六)包装类

    一.包装类 JAVA是一种面向对象语言,java中的类把方法与数据连接在一起,但在JAVA中不能定义基本类型对象,为了能将基本类型视为对象进行处理,java为每个基本类型都提供了包装类. 对应关系如下 ...

  7. Google安装postman插件

    1.保证网上商店可用 http://jingyan.baidu.com/article/48a42057ea53a1a9242504c1.html

  8. Java 不可变类

    Java 不可变类 immutable object 不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值. 如JDK内部自带的很多不可变类:Interger.Long和String等. * ...

  9. [ZOJ3316]:Game

    题面 vjudge Sol 有一个棋盘,棋盘上有一些棋子,两个人轮流拿棋,第一个人可以随意拿,以后每一个人拿走的棋子与上一个人拿走的棋子的曼哈顿距离不得超过L,无法拿棋的人输,问后手能否胜利 首先距离 ...

  10. layui-学习01-基本api

    全局配置 layui.config({ dir: '/res/layui/', //layui.js 所在路径(注意,如果是script单独引入layui.js,无需设定该参数.),一般情况下可以无视 ...