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;
    }
  • 相关阅读:
    UVa 1451 Average (斜率优化)
    POJ 1160 Post Office (四边形不等式优化DP)
    HDU 3507 Print Article (斜率DP)
    LightOJ 1427 Substring Frequency (II) (AC自动机)
    UVa 10245 The Closest Pair Problem (分治)
    POJ 1741 Tree (树分治)
    HDU 3487 Play with Chain (Splay)
    POJ 2828 Buy Tickets (线段树)
    HDU 3723 Delta Wave (高精度+calelan数)
    UVa 1625 Color Length (DP)
  • 原文地址:https://www.cnblogs.com/qlky/p/5655556.html
Copyright © 2011-2022 走看看