员工信息的定义如下:
Class Employee{
public int happy; //快乐值
public List<Employee> subordinates; //该员工的直接下属
}
公司的每个员工都符合上述类的描述。整个公司的人员结构都可看成是一棵标准的、没有环的多叉树。树的头结点是整个公司唯一的老板,除老板之外的员工都有唯一的直接上级。叶子结点是没有任何下属的基层员工(subordinates列表为空),除基层员工外,每个员工都有一个或多个直接下级。
这个公司现在要办party,你可以决定哪些员工来,哪些员工不来。但要遵循如下规则:
1.如果某个员工来了,那么这个员工的所有直接下级都不能来。
2.派对的整体快乐值是所有到场员工全部快乐值的累加。
3.你的目标是让派对的整体快乐值尽可能地大。
给定一棵多叉树的头结点boss,请返回派对的最大快乐值。
如何分析这个问题?我们还是可以采取递归的方式。对于任意一个员工都有两种可能性——来或不来。如果来,那么该员工的所有直接下属都不能来。但是他下属的下属还是可以来的。因此,对应于该员工来的情况下,我们可以计算出一个他的下属不来时的快乐值;如果该员工不来,那么他的所有直接下属都可以来,当然也可以选择不来,这种情况下,我们就需要在他所有下属来与不来之间选择出一个最大值。计算完毕之后,再递归地进行这个过程。
我们先来看看核心方法:
1 private static Info process(Employee node) { 2 if (node.subordinates.isEmpty()) { 3 return new Info(node.happy, 0); 4 } 5 int come = node.happy; //该员工来的情况下,整棵树的最大收益 6 int go = 0; //该员工不来的情况下,整棵树的最大收益 7 for (Employee next : node.subordinates) { 8 Info nextInfo = process(next); 9 go += Math.max(nextInfo.comeMaxHappy, nextInfo.goMaxHappy); 10 come += nextInfo.goMaxHappy; 11 } 12 return new Info(come, go); 13 }
这是一个递归函数,因此第一步就是设置递归结束条件。当递归到基层员工时,就该结束了。对于基层员工,他若来,快乐值就是happy;若不来,就是0.直接把这个对象返回出去。其次,我们设置若来时的快乐值come和不来时的快乐值go.然后遍历当前员工的所有直接下属。我们取得来时的快乐值和不来时的快乐值并进行累加。最后创建一个对象并返回出去。
接下来是提供给外界的方法:
1 public static int maxHappy(Employee boss) { 2 Info headInfo = process(boss); 3 return Math.max(headInfo.comeMaxHappy, headInfo.goMaxHappy); 4 }
显然,我们只需知道来和不来二者之间谁最大就行了。
测试代码如下:
1 import java.util.ArrayList; 2 3 public class MaxHappy { 4 private static class Employee { 5 public int happy; 6 //员工的所有直接下属员工,若员工为基层员工,则该列表为空 7 public ArrayList<Employee> subordinates; 8 public Employee(int happy) { 9 this.happy = happy; 10 subordinates = new ArrayList<>(); 11 } 12 } 13 14 private static class Info { 15 public int comeMaxHappy; //来的最大快乐值 16 public int goMaxHappy; //不来的最大快乐值 17 18 public Info(int comeMaxHappy, int goMaxHappy) { 19 this.comeMaxHappy = comeMaxHappy; 20 this.goMaxHappy = goMaxHappy; 21 } 22 } 23 24 private static Info process(Employee node) { 25 if (node.subordinates.isEmpty()) { 26 return new Info(node.happy, 0); 27 } 28 int come = node.happy; //该员工来的情况下,整棵树的最大收益 29 int go = 0; //该员工不来的情况下,整棵树的最大收益 30 for (Employee next : node.subordinates) { 31 Info nextInfo = process(next); 32 go += Math.max(nextInfo.comeMaxHappy, nextInfo.goMaxHappy); 33 come += nextInfo.goMaxHappy; 34 } 35 return new Info(come, go); 36 } 37 38 public static int maxHappy(Employee boss) { 39 Info headInfo = process(boss); 40 return Math.max(headInfo.comeMaxHappy, headInfo.goMaxHappy); 41 } 42 43 public static void main(String[] args) { 44 Employee employee46 = new Employee(46); 45 Employee employee12 = new Employee(12); 46 Employee employee30 = new Employee(30); 47 Employee employee1 = new Employee(1); 48 Employee employee3 = new Employee(3); 49 Employee employee7 = new Employee(7); 50 Employee employee90 = new Employee(90); 51 Employee employee40 = new Employee(40); 52 Employee employee25 = new Employee(25); 53 Employee employee8 = new Employee(8); 54 employee8.subordinates.add(employee25); 55 employee8.subordinates.add(employee40); 56 employee40.subordinates.add(employee1); 57 employee40.subordinates.add(employee3); 58 employee40.subordinates.add(employee7); 59 employee25.subordinates.add(employee90); 60 employee7.subordinates.add(employee12); 61 employee7.subordinates.add(employee30); 62 employee1.subordinates.add(employee46); 63 int maxHappyValue = maxHappy(employee8); 64 System.out.println(maxHappyValue); 65 } 66 }