Bootstrap

数据结构预算法-动态规划-树形dp(没有上司的舞会,树的直径,树的中心,数字变换,二叉苹果树,战略游戏,皇宫看守)

基础

树形动态规划(树形 DP)是一种基于树状结构进行动态规划的算法设计方法,广泛应用于解决与树相关的优化问题。

概念

定义:树形 DP 以树作为数据结构,利用树的递归性质无环特性,自底向上或自顶向下地在树上进行状态转移,从而求解问题的最优解。与一般动态规划类似,树形 DP 通过把原问题分解为多个子问题,并保存子问题的解来避免重复计算,以提高算法效率。

原理基础:树的每个节点及其子树构成一个独立的子问题,父节点的状态往往依赖于子节点的状态。例如,在一棵表示家族关系的树中,要计算整个家族的某种属性(如财富总值),可以先计算每个子家族(以每个子节点为根的子树)的该属性值,再汇总到根节点。

实现步骤

定义状态:根据问题的性质,为树的每个节点定义合适的状态。状态通常包含与该节点及其子树相关的信息,例如,在计算树中最长路径问题时,可能定义状态为从该节点出发到子树中某一叶子节点的最长路径长度。

确定状态转移方程:这是树形 DP 的关键步骤。根据问题的逻辑,确定父节点状态如何由子节点状态推导得出。例如,对于求树的最大独立集(选取一些节点,使得任意两个选取的节点不相邻,且选取节点数量最多)问题,对于某节点i,其状态转移方程可能为:选择节点i时,最大独立集大小等于该节点值加上所有孙子节点的最大独立集大小之和;不选择节点i时,最大独立集大小等于所有子节点的最大独立集大小之和。即dp[i][0] = max(dp[i][0], dp[j][1])(j为i的子节点,表示不选i),dp[i][1] = w[i] + sum(dp[k][0])(k为j的子节点,表示选i,w[i]为节点i的值)。

选择遍历顺序:

自底向上:从叶子节点开始,逐步向上更新节点状态,直到根节点。这种方式适用于子节点状态确定后,父节点状态可以直接推导的问题。例如在计算树的节点深度时,叶子节点深度为 0,通过叶子节点深度可以计算其父节点深度,以此类推直到根节点。

自顶向下:从根节点出发,递归地向子节点传递信息并更新状态。适用于父节点状态影响子节点状态计算的问题。比如在一些需要考虑从根到当前节点路径信息的问题中,根节点的信息可以在向下遍历过程中传递给子节点。

初始化状态:根据问题的具体情况,为树的节点初始化状态值。例如,对于一些计数问题,可能初始值设为 0;对于求最值问题,可能初始值设为负无穷(求最大值时)或正无穷(求最小值时)。

计算结果:经过状态转移后,根节点的状态值通常就是问题的解。例如在计算树的直径(树中最长路径的长度)问题中,根节点最终计算得到的状态值就是树的直径。

引例(上司的舞会):

分析:

背景设定:Ural 大学有编号为 1 - N 的 N 名职员,他们的关系构成一棵以校长为根的树,树中父节点是子节点的直接上司。

数据信息:每个职员有一个快乐指数 Hi。

约束条件:召开周年庆宴会时,职员不愿意和直接上司一起参会。

目标任务:在满足上述条件的情况下,邀请部分职员参会,使所有参会职员的快乐指数总和最大,求这个最大值。

点i可以选择下面的点,不包括直接儿子,那么我们就设置两个状态,一个是1选择这个节点,0表示不邀请这个节点,那么f[i][1]= h[i]+max(f[son][0],f[son1][0]..........)

伪代码:

习题1(树的直径):

分析:

树是一种特殊的无向连通图,其中包含 n个结点和 n-1 条无向边。该问题旨在找出树中两个结点间的最长路径,这条最长路径被称为树的直径,其长度是路径上所有边的权值之和。

树形动态规划(DP)

状态定义:对于树中的每个结点i  ,定义两个状态量。

 dp1[i]:表示从结点i出发,向下遍历子树能得到的最长路径长度。

 dp2[i]:表示从结点i出发,向下遍历子树能得到的第二长路径长度。

状态转移:遍历结点i的所有子结点j,对于边(i,j),若 dp1[i]+ w(i,j)> dp1[i](w(i,j)为边(i,j)的权值),则更新 dp2[i]= dp1[i], dp1[i]= dp1[j]+w(i,j);若dp1[j]+w(i,j)>dp2[i] 且dp1[j]+ w(i,j)≤ dp1[i],则dp2[i]= dpl[j]+w(i,j)。

结果计算:树的直径长度为 max(dp1[i]+ dp2[i]),即遍历所有结点,取 dp1||与 dp2||之和的最大值。

伪代码:

习题2(树的中心):

分析:

给定一棵有 n个结点(编号为1到 n)和 n-1条带权无向边的树,目标是在树中找出一个特定的点,使得这个点到树中其他所有结点的最远路径距离在所有可能的点中是最小的。这个点被称为树的中心(或重心,在某些场景下概念有别,但此处类似),其寻找过程对于理解树的结构特性以及解决如网络布局、资源分配等相关实际问题有重要意义。

树形动态规划法

状态定义:对于树中的每个节点 i ,定义两个关键状态。

f1 :表示从节点  i出发,向下遍历其所在子树能达到的最长路径长度。

f2:表示从节点  i出发,不经过其所在子树,通过其父节点方向遍历其他部分能达到的最长路径长度。

状态转移:

计算  f1时,遍历节点  i的所有子节点  j,通过比较选择最长的子树路径进行更新。

计算  f2相对复杂,需要根据其父节点fa 的  f1和  f2信息来推导,要考虑不同情况以避免重复计算路径。

结果确定:经过状态转移计算后,对于每个节点i,其到其他节点的最远距离可由 f1 和f2 相关信息得出,通过比较所有节点的这个最远距离,找出最小值对应的节点即为所求。

伪代码:

习题3(数字变换):

分析

变换规则:对于一个正整数  ,计算其除本身外的所有约数之和  y,若y<x ,则x 与y 可相互变换。比如4 的约数为1 、2 ,约数之和(不包括4 本身)为3 ,所以4可变为3 ; 7的约数只有1 ,这里不考虑自身,约数和为 1, 1的约数为 1 ,约数和(不包括 1 本身)为0 ,所以 1可变为 0 。但是12的约数有1,2,3,4,6,和为16,所以不能相互转换。

范围限定:所有数字变换在不超过n的正整数范围内进行。

目标任务:求不断进行数字变换且不出现重复数字的最多变换步数。

这里注意,每一个点的约数一定是固定的,我们假设y是x的父亲,那么一定点一定只有一个父亲,但是可能有很多个儿子,这样的结构就很像是一个树了。这里要求我们求出最多的变换步数,不就是求这个树的直径吗?

伪代码:

习题4(二叉苹果树):

分析:

这是一道运用树形动态规划解决的优化问题,问题核心在于在满足保留特定数量树枝且与根节点连通的条件下,最大化保留苹果的数量。

树的结构:一棵二叉苹果树,共 n个节点,编号1-n  ,树根编号固定为1 ,且树中若有节点分叉,必为二叉(不存在只有一个子节点的情况)。

树枝描述:用树枝两端连接的节点编号来确定树枝位置。

剪枝要求:因树枝过多需剪枝,部分树枝(边)上长有苹果,给定要保留的树枝数量,目标是求出最多能留住的苹果数,且保留的树枝需最终与 1号点(根节点)连通。

这里的边上才是苹果(边权),节点没有存储苹果

伪代码:

习题5(战略游戏):

分析:

这是一个关于图论中树结构的覆盖问题,本质上属于树形动态规划应用场景,以下从问题描述、解题思路等方面介绍:

背景设定:鲍勃玩战略游戏时面临保护一座中世纪城市的任务,城市道路构成一棵树,每个节点上的士兵能观察到与之相连的所有边。

目标任务:要求在树的节点上放置最少数量的士兵,使所有边都能被观察到。

示例说明:以给定的简单树(有节点 0、1、2、3,边连接 0 - 1、1 - 2、1 - 3)为例,在节点 1 处放置 1 名士兵,就可观察到所有边。

解题思路(树形动态规划)

定义状态:对于树中的每个节点  ,定义两个状态量。

 f[i][0]:表示节点i上不放置士兵时,以  为根的子树能被观察到所有边所需的最少士兵数。

 f[i][1]:表示节点 i上放置士兵时,以  为根的子树能被观察到所有边所需的最少士兵数。

伪代码:

习题6(皇宫看守)

分析:

在太平王世子事件后,陆小凤成为皇上特聘的御前一品侍卫,负责皇宫的安保工作。皇宫的布局从午门到后宫嫔妃寝宫呈树状结构,部分宫殿之间可以互相望见。

宫殿布局:以树的形式呈现,每个节点代表一座宫殿。

守卫要求:每个宫殿都需要有人全天候看守,且不同宫殿安排看守所需的费用不同。

经费限制:陆小凤手上经费不足,无法在每个宫殿都安置留守侍卫

这道题和上一个题目的区别在于,上一个题目要求的是同一个边的两个端点至少有一个点,因为花费是一样的,但是这里的要求是点和某些点之间可以相互看见,就是以点为最小单位,而非边

伪代码:

;