zoukankan      html  css  js  c++  java
  • HDU 1520 Anniversary party 树状dp

    HDU 1520 Anniversary party 树状dp

    题意

    大体意思说,一个大学要开一个party,大学里会有很多人回去参加,但是并不是很多人都愿意去,因为有可能遇到自己的直接上司。本来是一个放松的场所,遇到自己的直接boss可真的不大放得开,遇到上上级boss还可以,这就给组织这个活动的部门一个难题,每个人都有自己的开心值,我们该怎么做才能既避免这种尴尬,又能使得参加人的开心值总和最大呢?

    先给一个n表示大学里面人的个数,编号从1开始,然后是n个值,表示每个人的开心值,接下来是若干个关系,如1 3表示第三号是第一号的直接boss,当输入0 0的时候表示结束。

    这里是保证关系是一个树,而不会有若干个树。

    解题思路

    显然这是个求解最优的题目,我们可以使用动态规划来进行解决,因为这个关系是一个树状的,所以也就称为树状dp了。

    这里我们先定义一个状态,dp[i][0]表示在第i号员工不参加的情况下,以他为根节点的树的最大值,同样的,dp[i][1]就表示在第i号员工参加的情况下,以他为根节点树的最大值。

    对于初始化,dp[i][0]=0, dp[i][1]=他参加的开心值

    递推关系,这里dp[i][1]={dp[son1][0]+dp[son2][0]+... 。son1,son2等表示i的直接孩子编号}就是一个父节点参加,那么以他为根节点的树的最优值,就是以他的各个孩子节点(不参加时)为根节点树的最优值的和(这里满足最优子结构性质)。

    dp[i][0] += max(dp[son][1], dp[son][0]),要对i的每个孩子节点进行判断

    代码实现

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<stack>
    #include<queue>
    #include<map>
    #include<set>
    #include<sstream>
    typedef long long ll;
    using namespace std;
    const double esp=1e-6;
    const int inf=0x3f3f3f3f;
    const int MAXN=6e3+7;
    int fa[MAXN], dp[MAXN][2];
    vector<int> tre[MAXN];
    bool vis[MAXN];
    int n;
    void dfs(int rt)
    {
    	for(int i=0; i<tre[rt].size(); i++)
    		dfs(tre[rt][i]);
    	for(int i=0; i<tre[rt].size(); i++)
    	{
    		dp[rt][1] += dp[tre[rt][i]][0];
    		dp[rt][0] += max(dp[tre[rt][i]][0], dp[tre[rt][i]][1]);
    	}
    }
    int main()
    {
    	while(cin>>n)
    	{
    		for(int i=1; i<=n; i++){
    			cin>>dp[i][1];
    			vis[i] = false;
    			fa[i] = i;
    			dp[i][0] = 0;
    			tre[i].clear();
    		}
    		int a, b;
    		while(cin>>a>>b){
    			if(a == 0 && b == 0)
    				break;
    			fa[a] = b;
    			tre[b].push_back(a);
    		}
    		int root;
    		for(int i=1; i<=n; i++)
    			if(fa[i] == i){
    				root = i;
    				break;
    			}
    		dfs(root);
    		cout<<max(dp[root][1], dp[root][0])<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    sql&nbsp;一些语法&nbsp;聚合函数,…
    SQL标准
    margin:auto 和margin:0 auto的区别
    div居中
    相对问题和绝对问题
    有三行文字,每行最多80个字符,求其中大写字母,小写字母,数字,空格和其他
    输入n个字符串,将以A打头的字符串输出
    判断一个字符串是否是回文字符串
    从键盘键入5个国家的名字,按字典序输出
    输入五个字符串,输出最长的字符串
  • 原文地址:https://www.cnblogs.com/alking1001/p/12581471.html
Copyright © 2011-2022 走看看