树形dp入门模板题-没有上司的舞会(动态规划)

题目描述

某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入格式

第一行一个整数N。(1<=N<=6000)

接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)

接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。

最后一行输入0 0

输出格式

输出最大的快乐指数。

输入 #1

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

输出 #1

5

题目链接(洛谷)

树形dp
先来说一说个人对树形dp的理解,在思维上,其实它和我们常见的线性dp差不多,只是它递推的表现形式不是线性的,而是树形的推出来。在代码的写法上,常见的线性dp基本上用的是迭代的形式,也就是for循环,而树形dp是像树一样递推出来的,所有用的更多的是dfs和递归的写法。我们直接拿上面这道模板题来感受下树形dp。

题目中每一个职员都有两种情况,一种是参加,另一种是不参加。我们可以用一个二维数组来表示, dp[n+1][2] ,dp[i][0]表示该职员不参加时的最大快乐值,dp[i][1]表示该职员参加的最大快乐值。当该职员参加时,他的所有下属都不能参加即dp[y][0],将所有下属不参加的值加起来即可。当该职员不参加时,他的所有下属可以参加也可以不参加,取最大值加起来就可以了,即Max(dp[y][0],dp[y][1])。光看文字是很枯燥的,建议拿笔在纸上画一画,很快理解了。

参考代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main 
{    
    public static void main(String args[]) 
    {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        //存储每个职员参加的快乐指数
        int[] rs=new int[n+1];
        for(int i=1;i<=n;i++)
        	rs[i]=sc.nextInt();
        //记录每一个节点的所有子节点
        List> ps=new ArrayList>();
        for(int i=0;i<=n;i++)
        	ps.add(new ArrayList());
        int[] book=new int[n+1];
        for(int i=1;i> ps,int[] rs, int[][] dp, int root) 
	{
		
		dp[root][1]=rs[root];
		for(int i=0;i

你可能感兴趣的:(动态规划)