现在的位置: 首页 > 综合 > 正文

dp优化专辑 C – Anniversary party [树形dp]

2013年02月26日 ⁄ 综合 ⁄ 共 1197字 ⁄ 字号 评论关闭

看到了一样的题,直接把POJ上的替贴了进来,发现TLE了哭哭哭HDU上的测试数也太多了吧,分析了下POJ的代码,发现时间复杂度过高(有点暴力倾向),只要修改代码了。。。

题意:

某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。


思路:

任何一个点的取舍可以看作一种决策,那么状态就是在某个点取的时候或者不取的时候,以他为的子树能有的最大活跃总值。分别可以用f[i,1]f[i,0]表示第i个人来和不来直接记录在结构体中~

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
using namespace std;
#define N 6001
struct node
{
    int father;
    int child;
    int brother;
    int attend;//参加了
    int notattend;//没有参加
    void init()
    {
        father=0;
        child=0;
        brother=0;
        notattend=0;
    }
} p[N];
void dfs(int start)
{
    int child;
    child=p[start].child;
    while(child)
    {
        dfs(child);
        p[start].attend+=p[child].notattend;
        if(p[child].attend>p[child].notattend)
            p[start].notattend+=p[child].attend;
        else
            p[start].notattend+=p[child].notattend;
        child=p[child].brother;//兄弟结点
    }
}
int main()
{
    int n,root;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)
        {
            p[i].init();
            scanf("%d",&p[i].attend);
        }
        int a,b;
        while(scanf("%d%d",&a,&b),a||b)
        {
            root=b;
            p[a].father=b;
            p[a].brother=p[b].child;
            p[b].child=a;
        }
        while(p[root].father)//寻找父节点
            root=p[root].father;
        dfs(root);
        printf("%d\n",p[root].attend>p[root].notattend?p[root].attend:p[root].notattend);
    }
}

抱歉!评论已关闭.