标签:
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