树形DP递归问题

* 树形DP的递归套路:
* 分为以下4个步骤进行
* 1.以某个节点x为头节点的子树中(根据一个具体实例先分析),分析答案有哪些可能性,且这种可能性是以x的左子树,
* x的右子树和x整棵树为角度来进行考虑的。
* 2.根据第1步的可能性,列出对于x整棵树所需要的信息,
* 3.合并第2步的信息,对左树和右树提出同样的要求,得到最终需要的信息,构造一个类存储这些返回信息,
* 并以此作为返回类型。
* 4.设计递归函数,递归函数的返回答案是以x节点为根节点的情况下的答案
* 要通过调用左右子树的递归函数,得到左右子树的有关信息,通过左右子树的有关信息可以得到原树的信息,
* 并返回原树所需要类型的答案信息。

 

实例问题1:

获取一棵二叉树的最大距离(最大距离即为相距最远的两个节点之间有多少个节点)

 

* 思路:
* 将其分为两种情况进行讨论:
* 1.设取到最大距离时不经过根节点,则最大距离为左子树的最大距离或右子树的最大距离
* 2.设取到最大距离经过根节点,则最大距离为左子树高度+右子树高度+1
* 注:采用递归的思路求解,所以会有多棵子树(对应多个根节点)执行以上2个操作

 

代码:

 1 public static class Node{
 2         int value;
 3         Node left;
 4         Node right;
 5         
 6         public Node(int value) {
 7             this.value = value;
 8         }
 9     }
10     
11     public static class Info{//定义递归要返回的类型
12         int height;
13         int maxDistance;
14         
15         public Info(int height,int maxDistance) {
16             this.height = height;
17             this.maxDistance = maxDistance;
18         }
19     }
20     
21     public static int GetMaxDistance(Node root) {
22         return process(root).maxDistance;
23     }
24     
25     public static Info process(Node node) {
26         if (node == null) {
27             return new Info(0,0);
28         }
29         Info leftData = process(node.left);
30         Info rightData = process(node.right);
31         int height = Math.max(leftData.height, rightData.height) + 1;
32         int maxDistance = Math.max(leftData.height + rightData.height + 1, 
33                         Math.max(leftData.maxDistance, rightData.maxDistance));
34         return new Info(height,maxDistance);
35     }

 

实例问题2:

* 员工会议最大快乐值问题:
* 一个公司有多名员工,这些员工有着上下级关系,现规定每一个员工都有一个快乐值,且如果邀请该名员工来该会议,
* 则它的直接下级不能来参加这个会议(但间接下级则可以),现设计一种方案,使得所有参加会议的员工的快乐值总和
* 达到最大。

 

* 问题解析:
* 首先,员工的上下级就是一个树形结构,所以可以将其看作一个多叉树来进行分析,即可转换为所需要的n叉树问题,
* 使用树形DP的套路来进行求解即可。
*
* 树形DP分析:
* 1.通过题目分析可知,对一棵树所能得到的最大快乐值可以分两种情况来考虑:
* (1).将该根节点加入会议,则其下一层节点都不能加入会议。
* (2).不将该根节点加入会议,则其下一层的每个节点可以选择加入,也可以选择不加入,取二者的最大值。
*
* 2.通过分析得到对于每一棵树需要两个量:(1).加入根节点得到的快乐值 (2).不加入根节点得到的快乐值
*
* 3.分析发现对于所有子树都使用这种情况,所有构造一个类Info存入这两个变量值:yHappy,nHappy
*
* 4.构造递归函数:
* 要得到yHappy和nHappy
* yHappy = 下一层每个节点的nHappy相加
* nHappy = 下一层每个节点的max(yHappy,nHappy)相加

 

代码:

 1 public static class Employee{
 2         int happy;
 3         List<Employee> subordinates;
 4     }
 5     
 6     public static class Info{
 7         int yHappy;
 8         int nHappy;
 9         
10         public Info(int yHappy,int nHappy){
11             this.yHappy = yHappy;
12             this.nHappy = nHappy;
13         }
14     }
15     
16     public static Info process(Employee e) {
17         if (e.subordinates.isEmpty()) {
18             return new Info(e.happy,0);
19         }
20         int yHappy = e.happy;
21         int nHappy = 0;
22         for (Employee e1 : e.subordinates) {
23             Info nextInfo = process(e1);
24             yHappy += nextInfo.nHappy;
25             nHappy += Math.max(nextInfo.nHappy, nextInfo.yHappy);
26         }
27         return new Info(yHappy,nHappy);
28     }

 

posted @ 2022-05-07 19:53  jue1e0  阅读(43)  评论(0)    收藏  举报