多叉树
树状dp其实是比数组dp简单的。因为树状dp通过左右子树来决定当前节点的状态,就相当于普通dp已经知道了位置依赖,就是依赖于左右子树,所以只需要做决策就行。而普通dp还需要自己尝试来推出位置依赖的关系,故树形dp比较简单。
题目:某公司要举办一次晚会,每个参加晚会的人都不希望见到自己的直接上司,每个人有自己的活跃度,和上下级的关系,求邀请哪些人能使晚会的活跃度最大,最后返回活跃度即可。
例子:给定一个矩阵,
1 8
1 9
1 10
第0个数组为[1,8],表示0号员工的直接上级是1号员工,活跃度是8
第1个数组为[1,9],表示1号员工的直接上级是1号员工(大老板,头节
点),活跃度是9
第2个数组为[1,10],表示2号员工的直接上级是1号员工,活跃度是10
为了使气氛最活跃,应该1不来,0和2来,活跃度为18,返回18
import java.util.ArrayList;
import java.util.List;
public class MaxHappy {
//方法一: 树形dp
public static class Staff{
public int value;//自己的活跃度
public List<Staff> nexts;//所有下级
}
public static class RetuenType{
int laiMax;
int buMax;
public RetuenType(int laiMax, int buMax) {
this.laiMax = laiMax;
this.buMax = buMax;
}
}
public static RetuenType getMaxHappy(Staff head){
if (head.nexts.isEmpty()) {//我自己的代价
return new RetuenType(head.value, 0);
}
List<RetuenType> nextResults=new ArrayList<RetuenType>();
for (Staff next: head.nexts) {//遍历每一个下级
nextResults.add(getMaxHappy(next));
}
int buMax=0;
int laiMax=0;
for (RetuenType r:nextResults) {
laiMax+=r.buMax;
buMax+=Math.max(r.buMax, r.laiMax);
}
return new RetuenType(buMax, laiMax);
}
//方法二:用数组表示图的方法(没有生成整棵树)
public static int maxHappy(int[][] matrix) {
int[][] dp = new int[matrix.length][2];
boolean[] visited = new boolean[matrix.length];
int root = 0;
for (int i = 0; i < matrix.length; i++) {
if (i == matrix[i][0]) {
root = i;
}
}
process(matrix, dp, visited, root);
return Math.max(dp[root][0], dp[root][1]);
}
public static void process(int[][] matrix, int[][] dp, boolean[] visited, int root) {
visited[root] = true;
dp[root][1] = matrix[root][1];
for (int i = 0; i < matrix.length; i++) {
if (matrix[i][0] == root && !visited[i]) {
process(matrix, dp, visited, i);
dp[root][1] += dp[i][0];
dp[root][0] += Math.max(dp[i][1], dp[i][0]);
}
}
}
public static void main(String[] args) {
int[][] matrix = { { 1, 8 }, { 1, 9 }, { 1, 10 } };
System.out.println(maxHappy(matrix));
}
}