• 树形dp1——求树的最大独立集。


    树的最大独立集定义为:在无根树上找出最多的不相连的点。

    那么,怎么求最大独立集呢,用递归的思想构造动态规划。

    设dp(i)表示以i为根的树所拥有的最大独立集。

    那么我们思考转移,把问题变小发现,膜法转移,为什么呢,因为我们知道子问题,他的子树所拥有的最大独立集,却不能表示原问题的最大独立集。

    因为这不能单纯相加,所以我们思考,还有什么可以影响决策,我们发现,可以影响决策的还有一个东西,那就是是否在独立集内部。

    所以,dp(i,0)表示以i为根节点,并且i不在集合内部的最大独立集,如果i不在集合内部,那么他的子节点一定在或不在集合内部。

    所以dp(i,0)=∑max(dp(i的子节点,1),dp(i的子节点,0));

    dp(i,1)表示以i为根节点,并且i在集合内部的最大独立集,那么,以i为根的子节点一定不在集合内部。

    所以dp(i,1)=∑dp(i的子节点,0)。

    所以dp(i,1/0)=max(∑max(dp(i的子节点,1),dp(i的子节点,0)),∑dp(i的子节点,0));

    附上代码

    int dp(int u,int fa)
    {
        f[u][0]=1;
        f[u][1]=0;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==fa)continue;
            dp(v,u);
            f[u][0]+=f[v][1];
            f[u][1]+=max(f[v][0],f[v][1]);
        }
        return max(f[u][0],f[u][1]);
    }

    现在,来看一道题目

    LazyChild OJ(blackoj.pas/c/cpp)
    LazyChild 开了一家“善良 OJ”。但大多数人都不知道,这其实是家黑 OJ。亲爱的同学,请
    不要惊讶,古时候有黑店,现代为什么不能有黑 OJ 呢?每 AC 一道题,网站便会自动在电
    脑上安装一种木马。LazyChild 通过窃取信息获取收益(如网游帐号、OI 资料、YuanY
    TT 的照片等等)。
    作为一名资深黑客,老 Z 某日突然发现,“善良 OJ”上的木马,自己电脑上都没有。这可十
    分让他过意不去。老 Z 决定通过多 A 题,来丰富自己电脑的病毒库。
    经过调查,老 Z 发现,很多木马是不能共存的。比如“和谐”木马与“团结”木马,两者
    只能任选其一。然而,老 Z 是个完美主义者,他想要自己的病毒库尽可能充实。
    Z 不懈的追求最终感动了上天。天上的神仙(半仙?)“牛人雨”给这个问题稍稍降低了
    一点难度。神仙规定,对于 n 种木马,有且仅有(n-1)对不能共存,并且对于每种木马,都存
    在至少一个木马与之不能共存。
    Z 不在乎自己 AC 多少题。请告诉他,他最多能从“善良 OJ”上获取木马的个数。
    【输入】
    第一行,一个正整数 n,表示木马个数。
    剩余(n-1)行,每行一对木马,表示他们不能共存。(保证相同的木马可以共存,任意不同两
    行的描述不等价)
    木马编号从 0 (n-1)
    【输入】
    一行,老 Z 最多获得木马的个数。你可以认为开始时没有任何木马。
    【输入样例】
    3
    0 1
    1 2
    【输出样例】
    2
    【数据规模】
    对于 100%的数据,1<=n<=200 很明显的裸题。(*^▽^*)。

    附上代码

    #include<cstdio>
    #include<algorithm>
    #define N 200+10
    using namespace std;
    int f[N<<1][2],head[N<<1],num=1;
    struct Edge{
        int next,to;
    }e[N<<1];
    void add(int from,int to)
    {
        e[++num]=(Edge){head[from],to};
        head[from]=num;
    }
    void insert(int from,int to)
    {
        add(from,to);
        add(to,from);
    }
    int dp(int u,int fa)
    {
        f[u][0]=1;
        f[u][1]=0;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==fa)continue;
            dp(v,u);
            f[u][0]+=f[v][1];
            f[u][1]+=max(f[v][0],f[v][1]);
        }
        return max(f[u][0],f[u][1]);
    }
    int main()
    {
        freopen("blackoj.in","r",stdin);
        freopen("blackoj.out","w",stdout);
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            insert(u,v);
        }
        printf("%d
    ",dp(0,0));
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    【转】XP下安装IIS6.0的办法
    设计模式学习笔记十:单例模式(Singleton Pattern)
    linq学习笔记(2):DataContext
    设计模式学习笔记十二:桥接模式(Bridge Pattern)
    英文版c#数据结构
    linq学习笔记(3):Where
    一步步学习WCF(1):Hello
    linq学习笔记(5):Count/Sum/Min/Max/Avg
    [转]Asp.Net 面试题目收集
    从谷歌公司发现的十个至理名言
  • 原文地址:https://www.cnblogs.com/star-eternal/p/7683499.html
Copyright © 2020-2023  润新知