• 树形dp入门练习(hdu1011+hdu1061)


    hdu1011 和 hdu1561类似,给定每个节点的花费以及价值,并且子节点必须在父亲节点取到以后才可以被取到

    相当于是在树上进行的01背包

    dp时考虑每一个子树 root和它的每一个儿子,状态转移方程为

    dp[root][j]=max(dp[root][j],dp[root][j-k]+dp[ son[p] ][ k ])

    以下为ac代码

    hdu1011:这题有一个小坑,最后必须要剩余至少一个人。。开始没考虑到,一直wa

    #include<stdio.h>
    #include<iostream>
    #include<stdlib.h>
    #include<math.h>
    #include<ctype.h>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<queue>
    #define mod 1000000007
    #define MAX 100000000
    using namespace std;
    int t,n,m,p,k,tt;
    int map[105][105];
    int dp[105][105];
    int a[105];
    int w[105];
    int vi[105];
    void dfs(int s)
    {
        vi[s]=1;
        int cost=(w[s]+19)/20;
        for(int i=cost;i<=m;i++)
            dp[s][i]=a[s];
        for(int i=1;i<=n;i++)
        {
            if(!map[s][i])
                continue;
            if(vi[i])
                continue;
            dfs(i);
             for(int k=m;k>=cost;k--)
                for(int j=1;j+cost<=k;j++)
                    dp[s][k]=max(dp[s][k],dp[s][k-j]+dp[i][j]);
    
        }
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)&&(n!=-1||m!=-1))
        {
            int x,y;
            memset(map,0,sizeof(map));
            memset(dp,0,sizeof(dp));
            memset(vi,0,sizeof(vi));
            a[0]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",w+i,a+i);
            }
            for(int i=1;i<n;i++)
            {
                scanf("%d%d",&x,&y);
                map[x][y]=1;
                map[y][x]=1;
            }
            if(m==0)
            {
                puts("0");
                continue;
            }
            dfs(1);
            printf("%d
    ",dp[1][m]);
        }
        return 0;
    }

    hdu 1561

    #include<stdio.h>
    #include<iostream>
    #include<stdlib.h>
    #include<math.h>
    #include<ctype.h>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<queue>
    #define mod 1000000007
    #define MAX 100000000
    using namespace std;
    int t,n,m,p,k,tt;
    int map[201][201];
    int dp[201][201];
    int a[201];
    void dfs(int s)
    {
        for(int j=1;j<=m+1;j++)
            dp[s][j]=a[s];
        for(int i=1;i<=n;i++)
        {
            if(!map[s][i])
                continue;
            dfs(i);
             for(int k=m+1;k>=1;k--)
                for(int j=0;j+1<=k;j++)
                    dp[s][k]=max(dp[s][k],dp[s][k-j]+dp[i][j]);
    
        }
    
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)&&(n+m))
        {
            memset(map,0,sizeof(map));
            memset(dp,0,sizeof(dp));
            int x;
            a[0]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&x);
                map[x][i]=1;
                scanf("%d",a+i);
            }
            dfs(0);
            printf("%d
    ",dp[0][m+1]);
        }
        return 0;
    }
  • 相关阅读:
    Unity3d通用工具类之生成文件的MD5
    Unity3d-Socket之龙一编年史network.dll分析(2)-> CNetLogger
    Unity3d-Socket之龙一编年史network.dll分析(1)
    Unity3d设计模式之单例模式
    c#中的??运算符
    java 字节流
    java File文件操作
    java 线程池和lamda表达式
    java 线程状态(通信/等待/唤醒)
    java 线程安全
  • 原文地址:https://www.cnblogs.com/oneshot/p/3979873.html
Copyright © 2020-2023  润新知