Anniversary party 员工的活跃度问题 (树形dp)
一、题目
一个公司的上下节关系是一棵多叉树,这个公司要举办晚会,你作为组织者已经摸清了大家的心理:一个员工的直 接上级如果到场,这个员工肯定不会来。每个员工都有一个活跃度的值,决定谁来你会给这个员工发邀请函,怎么 让舞会的气氛最活跃?返回最大的活跃值。
举例:
给定一个矩阵来表述这种关系
matrix = { 1,6 1,5 1,4 }
这个矩阵的含义是:
matrix[0] = {1 , 6},表示0这个员工的直接上级为1,0这个员工自己的活跃度为6
matrix[1] = {1 , 5},表示1这个员工的直接上级为1(他自己是这个公司的最大boss),1这个员工自己的活跃度 为5
matrix[2] = {1 , 4},表示2这个员工的直接上级为1,2这个员工自己的活跃度为4
为了让晚会活跃度最大,应该让1不来,0和2来。最后返回活跃度为10
二、思路
对于这颗多叉树中的每个节点均有两种情况:
1.该节点来参加晚会,那么它的直接下级节点均不来参加。此时该节点的最大活跃值就是所有直接节点不来的活跃值相加。
2.该节点不来参加晚会,那么它的直接下级节点可以来也可以不来。此时该节点的最大活跃值是其直接节点中来或不来的活跃值中的较大值相加。
下面来举个例子:
以上这种情况明显是第一层的节点来,第二层节点都不来,第三层节点都来的情况下活跃度最大。
下面来看另外一个例子:
当第二层的最右边的元素活跃值为300时,显然要留住300的元素,此时第一层元素必须不能来,而第二层的值为5,4元素可以来也可以不来。
三、代码
1 public class MaxHappy { 2 //matrix 第一维代表直接上级,第二维代表活跃值 3 public static int maxHappy(int[][] matrix){ 4 //dp[i][0]表示的是i作为父节点,它不来的时候的最大活跃度; 5 //dp[i][1]表示的是i作为父节点,它来的时候的最大活跃度; 6 int[][] dp = new int[matrix.length][2]; 7 boolean[] visited = new boolean[matrix.length];//记录每个员工来不来 8 int root = 0; 9 //找到老板节点 10 for(int i=0;i<matrix.length;i++){ 11 if(i==matrix[i][0]){ 12 root = i; 13 } 14 } 15 process(matrix, dp, visited, root); 16 return Math.max(dp[root][0],dp[root][1]); 17 } 18 19 public static void process(int[][] matrix,int[][] dp,boolean[] visited,int root){ 20 visited[root] = true;////标记当前结点已经做过父 也就是它的dp两个值都算出来了 21 dp[root][1] = matrix[root][1];//初始化来的时候的活跃度 22 for(int i=0;i<matrix.length;i++){ 23 if(matrix[i][0]==root&&!visited[i]){ 24 process(matrix, dp, visited, i); 25 dp[root][1] += dp[i][0]; //当root来,则加上root的每个直接下级不来的时候的活跃度 26 dp[root][0] += Math.max(dp[i][1], dp[i][0]); //当root不来,则每个直接下级可以来也可以不来,加上较大的活跃度 27 } 28 } 29 } 30 /* 31 public static void main(String[] args) { 32 int [][] matrix = {{1,8},{1,9},{1,3}}; 33 System.out.println(maxHappy(matrix)); 34 } 35 */ 36 }