zoukankan      html  css  js  c++  java
  • hdu 1561 树形背包 选k个最大价值

    http://blog.csdn.net/dellaserss/article/details/8799730

    这题其实和上一题思路是一样的,一个0节点作为根节点,通过剩余量来遍历子树。

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <cctype>
    #include <vector>
    #include <iterator>
    #include <set>
    #include <map>
    #include <sstream>
    using namespace std;
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pf printf
    #define sf scanf
    #define spf sprintf
    #define pb push_back
    #define debug printf("!
    ")
    #define MAXN 205
    #define MAX(a,b) a>b?a:b
    #define blank pf("
    ")
    #define LL long long
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define pqueue priority_queue
    #define INF 0x3f3f3f3f
    
    int n,m;
    
    struct node
    {
        int y,next;
    }tree[1000];
    
    int head[MAXN],dp[MAXN][MAXN],ptr=1;
    
    int sum[MAXN],vl[MAXN],vis[MAXN];
    
    
    void add(int x,int y)
    {
        tree[ptr].y = y;
        tree[ptr].next = head[x];
        head[x] = ptr++;
    }
    
    void dfs(int root)
    {
        if(vis[root]) return;
        int i,j,k;
        vis[root] = sum[root] = 1;
        int tot = 0;
    
        for(i=head[root]; i!=-1; i=tree[i].next)
        {
            int p = tree[i].y;
    
            if(!vis[p])
            {
                dfs(p);
                sum[root]+=sum[p];
                tot++;
                //pf("i%d p%d tot%d sum%d
    ",root,p,tot,sum[root]);
            }
        }
    
        dp[root][1] = vl[root];
    
        for(i=head[root]; i!=-1; i=tree[i].next)
        {
            int p = tree[i].y;
    
            for(j = sum[root];j>1;j--)
            {
                for(k = 1;k<j;k++)
                {
                    if(dp[root][k]!=-1 && dp[p][j-k]!=-1)
                    {
                        dp[root][j] = max(dp[root][j],dp[root][k]+dp[p][j-k]);
                        //pf("i%d j%d k%d p%d dp%d
    ",root,j,k,p,dp[root][j]);
                    }
                }
            }
        }
    }
    
    int main()
    {
        int i,j,k,a,b;
        while(~sf("%d%d",&n,&m) && m+n>0)
        {
            mem(head,-1);
            ptr = 1;
    
            for(i=1;i<=n;i++)
            {
                sf("%d%d",&a,&b);
                add(i,a);
                add(a,i);
                vl[i] = b;
            }
            mem(dp,-1);
            mem(vis,0);
            dfs(0);
            pf("%d
    ",dp[0][m+1]);
        }
        return 0;
    }

    但我发现这道题因为要统计子节点数量,其实用邻接表更方便一些:(但速度会慢很多)

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <cctype>
    #include <vector>
    #include <iterator>
    #include <set>
    #include <map>
    #include <sstream>
    using namespace std;
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pf printf
    #define sf scanf
    #define spf sprintf
    #define pb push_back
    #define debug printf("!
    ")
    #define MAXN 205
    #define MAX(a,b) a>b?a:b
    #define blank pf("
    ")
    #define LL long long
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define pqueue priority_queue
    #define INF 0x3f3f3f3f
    
    int n,m;
    
    struct node
    {
        int y,next;
    }tree[1000];
    
    int head[MAXN],dp[MAXN][MAXN],ptr=1;
    
    int sum[MAXN],vl[MAXN],vis[MAXN];
    
    vector<int> son[1000];
    
    void dfs(int root)
    {
        int i,j,k;
    
        for(i=0;i<son[root].size();i++)
        {
            int p = son[root][i];
    
            if(son[p].size()>0) dfs(p);
    
            for(j=m;j>1;j--)
            {
                for(k=1;k<j;k++)
                {
                    dp[root][j] = max(dp[root][j],dp[root][k] + dp[p][j-k]);
                    //pf("i%d j%d k%d p%d dp%d
    ",root,j,k,p,dp[root][j]);
                }
            }
        }
    }
    
    int main()
    {
        int i,j,k,a,b;
        while(~sf("%d%d",&n,&m) && m+n>0)
        {
            mem(dp,0);
            m++;
    
            for(i=0;i<=n;i++) son[i].clear();
    
            for(i=1;i<=n;i++)
            {
                sf("%d%d",&a,&b);
                son[a].pb(i);
                for(j=1;j<=m;j++) dp[i][j] = b;
            }
            dfs(0);
            pf("%d
    ",dp[0][m]);
        }
        return 0;
    }
  • 相关阅读:
    基于python内置方法进行代码混淆
    python-__getattr__ 和 __getattribute__
    python-flask学习
    python-创建进程的三种方式
    python-property、__get__、__set__
    call apply bind
    【算法】js实现最短时间走完不同速度的路程
    图片懒加载实现
    MoonLight可视化订单需求区域分析系统前端
    前端代码基本命名规范和格式规范
  • 原文地址:https://www.cnblogs.com/qlky/p/5655556.html
Copyright © 2011-2022 走看看