hdu 1520 Anniversary party 树形dp入门

来源:互联网 发布:电子数据取证软件 编辑:程序博客网 时间:2024/05/16 07:47

题目大意:
n个人参加聚会,编号1-n,上下属关系构成一棵树,其中每个人和直接上属不能同时参加,每人有个高兴度,问参加聚会的最大高兴度。

思路:
树形dp即树上的dp, 根据孩子的状态推出父结点状态;
dp[root][0]表示root作为祖节点的子树中root不参加的最大高兴度,dp[root][1]表示root参加的最大高兴度。则有
dp[root][0] = SUM max(dp[son][1], dp[son][0]),
dp[root][1] = SUM dp[son][0];
答案即为max(dp[root][1], dp[root][0];

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 6010;struct node{    int value;    int son, brother;};node tree[MAXN];        //静态链表、孩子兄弟表示int n;int dp[MAXN][2];int vis[MAXN];void dfs(int r){    dp[r][0] = 0;    dp[r][1] = tree[r].value;    if(tree[r].son)    {        int t = tree[r].son;        while(t)        {            dfs(t);            dp[r][0] += max(dp[t][0], dp[t][1]);            dp[r][1] += dp[t][0];            t = tree[t].brother;        }    }}int main(int argc, char const *argv[]){    while(~scanf("%d", &n))    //不止一组数据。。。    {        for(int i = 1; i <= n; i++)        {            scanf("%d", &tree[i].value);            tree[i].son = 0;            tree[i].brother = 0;        }        int x, y;        memset(vis, 0, sizeof(vis));        while(scanf("%d%d", &x, &y), x + y)        {            vis[x] = 1;            if(!tree[y].son)                tree[y].son = x;            else            {                int t = tree[y].son;                while(tree[t].brother)                    t = tree[t].brother;                tree[t].brother = x;            }        }        int root = 1;        while(vis[root] && root < n)  //找出祖节点            root++;        dfs(root);        printf("%d\n", max(dp[root][0], dp[root][1]));    }    return 0;}
0 0
原创粉丝点击