Description
Input
Output
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
题目大意:
题目大概说的是,一个公司要举行一个party ,让每个人参加的话就会增加一定的欢乐程度,为了排除尴尬的场面,每个人和他的直接领导不能同时来参加,给你一个 n ,说明有 n 个人,然后 接着 n 行 表示 让每个人去所增加的欢乐程度,接着每行输入两个说 l 和 k ,表示 k 是 l 的直属上司,直到输入为 0 0 时该组输入结束,输出所能达到的最大的欢乐值。
思路分析:
每个人能不能参加与他的直属上司参加不参加有关,如果他的上司参加了,那么他就不能参加,如果他的上司没参加,那么他可以参加也可以不参加,我们现在用 dp[i][0] 表示 i 不参加的欢乐值,dp[i][1] 表示 i 参加的欢乐值,那么我们可以推出一个状态转移方程
                        dp[k][1] += dp[l][0];
			dp[k][0] += max(dp[l][0],dp[l][1]);
因此,我们就可以用这个状态转移方程求解。
这道题出现了一个令我很无语的情况,那就是在 HDU oj 上 用 c++ 编译器能过,而用 G++ 编译器超时,所以大家提交的时候注意点
附上一些我找到的 c++ 与 g++ 的差别链接:http://blog.csdn.net/xia842655187/article/details/51329012点击打开链接
附上代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;
int dp[6500][2];
int visit[6500],n,father[6500];
void dfs(int root)                           //  利用 深搜从根开始往下搜,搜到最后一层厚,慢慢的网上递推转移
{
	visit[root] = 1;
	for(int i = 1;i <= n;i++)
	{
		if(father[i] == root && !visit[i])        //   root 是 i 的上司,那么就对 i 作为一个新根进行往下搜索
		{
			dfs(i);
			dp[root][1] += dp[i][0];                 //  root 去的时候,i 肯定不能去,所以 加上 dp[i][0]
			dp[root][0] += max(dp[i][0],dp[i][1]);  //  root 不去的时候 从 i 去和不去中选一个最大值
		}
	}
}
int main()
{
	while(cin >> n)
	{
		memset(dp,0,sizeof(dp));
		for(int i = 1;i <= n;i++)
		{
			scanf("%d",&dp[i][1]);
		}
		fill(father,father + 6500,0);          //  将每个人的直属上司初始化为 0 
		int l ,k,root = 0;
		while(cin >> l >> k && l + k)          //  对 每个人的直属上司进行标记
		{
			father[l] = k;
			root = k;
		}
		while(1)                               //  判断查询到树的根
		{
			if(father[root] == 0)
			break;
			root = father[root];
		}
		memset(visit,0,sizeof(visit));
		dfs(root);         //  从根开始查询
		cout << max(dp[root][0],dp[root][1]) << endl;        //  从 大 boss 去与不去中选择一个 欢乐值最大的输出
	}
	return 0;
}HDU 1520 & POJ 2342 Anniversary party(树形dp)
原文:http://blog.csdn.net/xia842655187/article/details/51334691