我虽然做了好几道树形背包的题,但是一直不是十分理解,对于每一道题,总是看题解就明白,然后换一道题自己写不出来。临近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. Mybatis JdbcType与Oracle、MySql数据类型对应列表

    1. Mybatis JdbcType与Oracle.MySql数据类型对应列表 Mybatis JdbcType Oracle MySql JdbcType ARRAY     JdbcType B ...

  2. Magento 2开发教程 - 如何添加新产品属性

    添加产品属性是一种在Magento 1 和 Magento 2最受欢迎的业务. 属性是解决许多与产品相关的实际任务的有力方法. 这是一个相当广泛的话题,但在这个视频中,我们将讨论添加一个下拉类型属性到 ...

  3. Eclipse 工具栏无法移动的解决办法

    升级到Juno后发现工具栏有些乱 而且无法拖动,试了下http://blog.csdn.net/cxx504659987/article/details/38532599的方法 发现配置文件里没有文中 ...

  4. SQL执行一次INSERT INTO查询,插入多行记录

    那如果我们想插入多行记录呢?可能你会想到多次运行INSERT语句即可,就像下面的php代码示例: INSERT INTO tbl_name (col1,col2) VALUES (,); 那如果我们想 ...

  5. [android] 练习样式主题自定义activity切换动画

    主要练习了自定义样式和主题,继承android系统默认的样式并修改,练习xml定义淡入淡出动画 anim/fade_in.xml <?xml version="1.0" en ...

  6. 启动memcache 服务器端

    # memcached -d -m 10 -u root -p 11211 -c 256 -P /tmp/memcached.pid -d选项是启动一个守护进程, -m是分配给Memcache使用的内 ...

  7. 你必须知道的get与post的真正区别

    我们会经常看到有人问:http协议中GET请求和POST请求有什么区别~? 这个问题看似很简单,但是不同程度的人会回答出不同的结果.在公司的面试中,也会经常的问及类似这样的问题,看似很简单,但是不同层 ...

  8. eclipse Java类 红色感叹号 commit失败

    解决方法:  1.进入java类文件所在物理目录 (e:\workspace\myproject\...) 2. 删除多余的版本管理工具的文件或文件夹(如 .svn) 3. 刷新eclipse工程 4 ...

  9. HDU4336:Card Collector(min-max容斥)

    题面 传送门 Sol 方法一 直接状压就好了 # include <bits/stdc++.h> # define RG register # define IL inline # def ...

  10. Bzoj3105:[CQOI2013]新Nim游戏

    题面 传送门 Sol 也是拿出一些数,使剩下的异或起来不为\(0\) 而线性基内的数异或不出\(0\) 那么从大到小加到线性基内 然后中途为\(0\)了,就取走它 这样我们使最大的在线性基内,剩下的是 ...