1. /**
    2. * 最大快乐值
    3. * 公司的每个员工共都符合Employee类的描述.整个公司的人员结构可以看作是一颗标准的,没有环的多
    4. * 叉树。树的头节点是公司唯一的老板,除老板之外的每一个员工都有一个唯一的直接上级。叶节点是没
    5. * 有任何下属的基层员工(subordinates列表为空),除基层员工之外,每个员工都有一个或者多个直
    6. * 接下级。
    7. */
    8. public class Code04_MaxHappy {
    9. public static class Employee {
    10. public int happy; // 快乐值
    11. public List<Employee> nexts; // 直系下级
    12. public Employee(int h) {
    13. happy = h;
    14. nexts = new ArrayList<>();
    15. }
    16. }
    17. public static int maxHappy1(Employee boss) {
    18. if (boss == null) {
    19. return 0;
    20. }
    21. return process1(boss, false);
    22. }
    23. // 当前来到的节点叫cur,
    24. // up表示cur的上级是否来,
    25. // 该函数含义:
    26. // 如果up为true,表示在cur上级已经确定来,的情况下,cur整棵树能够提供最大的快乐值是多少?
    27. // 如果up为false,表示在cur上级已经确定不来,的情况下,cur整棵树能够提供最大的快乐值是多少?
    28. public static int process1(Employee cur, boolean up) {
    29. if (up) { // 如果cur的上级来的话,cur没得选,只能不来
    30. int ans = 0;
    31. for (Employee next : cur.nexts) {
    32. ans += process1(next, false);
    33. }
    34. return ans;
    35. } else { // 如果cur的上级不来的话,cur可以选,可以来也可以不来
    36. int p1 = cur.happy;
    37. int p2 = 0;
    38. for (Employee next : cur.nexts) {
    39. p1 += process1(next, true);
    40. p2 += process1(next, false);
    41. }
    42. return Math.max(p1, p2);
    43. }
    44. }
    45. /**
    46. * 递归套路解决
    47. */
    48. public static int maxHappy2(Employee head) {
    49. Info allInfo = process(head);
    50. return Math.max(allInfo.no, allInfo.yes);
    51. }
    52. public static class Info {
    53. public int no; // 头节点不来时的最大happy收益
    54. public int yes; // 头节点来时的最大happy收益
    55. public Info(int n, int y) {
    56. no = n;
    57. yes = y;
    58. }
    59. }
    60. public static Info process(Employee x) {
    61. if (x == null) {
    62. return new Info(0, 0);
    63. }
    64. int no = 0;
    65. int yes = x.happy;
    66. // 获取后代信息
    67. for (Employee next : x.nexts) {
    68. Info nextInfo = process(next);
    69. no += Math.max(nextInfo.no, nextInfo.yes);// 头节点来时,最大happy收益值
    70. yes += nextInfo.no;
    71. }
    72. return new Info(no, yes);
    73. }
    74. // for test
    75. public static Employee genarateBoss(int maxLevel, int maxNexts, int maxHappy) {
    76. if (Math.random() < 0.02) {
    77. return null;
    78. }
    79. Employee boss = new Employee((int) (Math.random() * (maxHappy + 1)));
    80. genarateNexts(boss, 1, maxLevel, maxNexts, maxHappy);
    81. return boss;
    82. }
    83. // for test
    84. public static void genarateNexts(Employee e, int level, int maxLevel, int maxNexts, int maxHappy) {
    85. if (level > maxLevel) {
    86. return;
    87. }
    88. int nextsSize = (int) (Math.random() * (maxNexts + 1));
    89. for (int i = 0; i < nextsSize; i++) {
    90. Employee next = new Employee((int) (Math.random() * (maxHappy + 1)));
    91. e.nexts.add(next);
    92. genarateNexts(next, level + 1, maxLevel, maxNexts, maxHappy);
    93. }
    94. }
    95. public static void main(String[] args) {
    96. int maxLevel = 4;
    97. int maxNexts = 7;
    98. int maxHappy = 100;
    99. int testTimes = 100000;
    100. for (int i = 0; i < testTimes; i++) {
    101. Employee boss = genarateBoss(maxLevel, maxNexts, maxHappy);
    102. if (maxHappy1(boss) != maxHappy2(boss)) {
    103. System.out.println("Oops!");
    104. }
    105. }
    106. System.out.println("finish!");
    107. }
    108. }