• 树形DP习题


    听闻noip要考树形DP,本蒟蒻万分惶恐,特刷一坨题目,以慰受惊之心。

    codevs 1486

    /*和非常出名的“选课”是一个题*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 1010
    using namespace std;
    int son[N][2],f[N][N],v[N],n,m,flag;
    int dfs(int x,int y)
    {
        if(f[x][y]!=-1)return f[x][y];
        if(x==0||y<=0)
        {
            if(!flag)flag=1;
            else return 0;
        }
        f[x][y]=dfs(son[x][1],y);
        for(int i=0;i<=y-1;i++)
          f[x][y]=max(f[x][y],dfs(son[x][0],i)+dfs(son[x][1],y-1-i)+v[x]);
        return f[x][y];
    }
    int main()
    {
        memset(f,-1,sizeof(f));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
          scanf("%d",&v[i]);
        for(int i=1;i<=n;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            if(!son[x][0])son[x][0]=y;
            else
            {
                x=son[x][0];
                while(son[x][1])x=son[x][1];
                son[x][1]=y;
            }
        }
        printf("%d",dfs(0,m+1));
        return 0;
    }

    codevs 1163

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 110
    using namespace std;
    int son[N][2],cost[N],val[N],f[N][N*6],n,m,p=1;
    void build(int x)
    {
        if(val[x])return;
        son[x][0]=++p;build(p);
        son[x][1]=++p;build(p);
    }
    int dfs(int x,int y)
    {
        if(f[x][y]!=-1)return f[x][y];
        if(y<=0)return 0;
        if(val[x])return min(val[x],(y/5));
        int s0=son[x][0],s1=son[x][1];
        f[x][y]=max(dfs(s0,y-cost[s0]),dfs(s1,y-cost[s1]));
        for(int i=0;i<=y;i++)
          f[x][y]=max(f[x][y],dfs(s0,i-cost[s0])+dfs(s1,y-i-cost[s1]));
        return f[x][y];
    }
    int main()
    {
        memset(f,-1,sizeof(f));
        scanf("%d",&m);
        int x,y;
        while(scanf("%d%d",&x,&y)!=EOF)
        {
            cost[++n]=x*2;val[n]=y;
        }
        build(1);
        printf("%d",dfs(1,m-cost[1]));
        return 0;
    }

    poj 1463

    /*
      题意:给定一棵树,要求选最少的点,是每条边至少有一个点被选中
      f[i][0/1]表示第i个点选或不选的最少花费。
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 1510
    using namespace std;
    int head[N],f[N][2],n,cnt;
    struct node
    {
        int v,pre;
    };node e[N*2];
    void add(int x,int y)
    {
        ++cnt;
        e[cnt].v=y;
        e[cnt].pre=head[x];
        head[x]=cnt;
    }
    void dfs(int x,int fa)
    {
        f[x][1]=1;
        for(int i=head[x];i;i=e[i].pre)
        {
            if(e[i].v==fa)continue;
            dfs(e[i].v,x);
            f[x][1]+=min(f[e[i].v][0],f[e[i].v][1]);
            f[x][0]+=f[e[i].v][1];
        }
    }
    int main()
    {
        freopen("jh.in","r",stdin);
        while(scanf("%d",&n)!=EOF)
        {
            cnt=0;
            memset(f,0,sizeof(f));
            memset(e,0,sizeof(e));
            memset(head,0,sizeof(head));
            for(int i=1;i<=n;i++)
            {
                int x,y,z;
                scanf("%d:(%d) ",&x,&y);
                for(int j=1;j<=y;j++)
                {
                    scanf("%d",&z);
                    add(x,z);add(z,x);
                }
            }
            dfs(0,-1);
            printf("%d
    ",min(f[0][0],f[0][1]));
        }
        return 0;
    }
  • 相关阅读:
    Socket_leaks open socket #5024 left in connection
    阿里云 如何减少备份使用量? mysql数据库的完整备份、差异备份、增量备份
    一个正则式引发的血案 贪婪、懒惰与独占
    linux下tmp目录里很多php开头的文件
    后端线上服务监控与报警方案
    架构先行
    数据盘缩容
    文件过滤 批量删除
    mock数据(模拟后台数据)
    如何避免升级 Linux 实例内核后无法启动
  • 原文地址:https://www.cnblogs.com/harden/p/6040819.html
Copyright © 2020-2023  润新知