• poj2342 Anniversary party(树形dp入门题)


    http://poj.org/problem?id=2342

    题目给你一个n表示总人数,然后又给了n个人的欢乐度,还有n-1个上下级关系。然后要求在n个人里选一些人,并且选的人里任意两人没有直接上下级的关系,问你最多可以选到的欢乐度是多少?

     题解:先定义状态dp[i][0]表示第i个人不去,子树i的最大欢乐度,dp[i][1]表示第i个人去,子树i的最大值。dp[i][1]先初始化为i节点的欢乐度,dp[i][0]初始化为0,随便选取一个点为根节点建一颗树,用dfs从上往下搜索,直到搜到了叶子节点,假设叶子节点j,因为叶子节点是没有儿子节点的,所以dp[j][0]=0,dp[j][1]=a[j],然后从叶子节点回溯到其父节点,对父节点(假设父节点i)的信息更新用,dp[i][0]+=max(dp[j][0],dp[j][1]),dp[i][1]+=dp[j][0],(这里之所以用+=是因为i节点的儿子节点可能不止一个),,就一直这样从下往上递推,最后max(dp[root][1],dp[root][0])就是要的答案.

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    #define maxn 6005
    vector<int>son[maxn];//相当于邻接表,用来存边关系
    bool vis[maxn];//标记访问过的节点
    int dp[maxn][2];
    void dfs(int root)//搜到叶子节点,然后回溯更新父节点的值
    {
        vis[root]=1;
        for(int i=0;i<son[root].size();i++)
        {
            int v=son[root][i];
            if(!vis[v])
            {
                dfs(v);
                dp[root][1]+=dp[v][0];
                dp[root][0]+=max(dp[v][0],dp[v][1]);
    
            }
        }
    }
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            son[i].clear();
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
                scanf("%d",&dp[i][1]);
                dp[i][0]=0;
        }
        int fa,so;
        while(scanf("%d%d",&so,&fa)!=EOF)
        {
            if(so==0&&fa==0) break;
            son[fa].push_back(so);
            son[so].push_back(fa);
        }
        dfs(1);//这里根节点是随便选取的
        cout<<max(dp[1][0],dp[1][1]);
    
    }
    
  • 相关阅读:
    Mysql(11)_Mysql权限与安全
    Mysql(10)_存储过程与流程控制
    Java(43)_AWT事件处理挂关闭生效
    6.实现合同测试用例
    6.测试库优化
    5.案例回顾及编写测试用例
    4.测试案例实现代码库与测试用例V2.0
    3.测试案例实现代码库与测试用例
    markdown语法学习
    1.faker批量随机造数据
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755089.html
Copyright © 2020-2023  润新知