首页 > 代码库 > 初涉分组背包 HDU 1561 The more,The better

初涉分组背包 HDU 1561 The more,The better

给出一个森林,每棵树均为一组物品,首先推出每棵树可以组成的物品种类。

然后是基本的分组背包模板。

即 最外层枚举组数,次外层枚举背包容量,内层枚举物品体积。

 对于每棵树有 ans[root][i+j] = ans[root][ i ] + ans[son][ j ]。

 题水数据也水,不多说了。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long int
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007
#define LM(a,b) (((ULL)(a))<<(b))
#define RM(a,b) (((ULL)(a))>>(b))

using namespace std;

const int MAXN = 210;

struct N
{
    int u,v,w,next;
} edge[MAXN*2];

int head[MAXN];

int Top;

void Link(int u,int v,int w = -1)
{
    edge[Top].u = u;
    edge[Top].v = v;
    edge[Top].w = w;
    edge[Top].next = head[u];
    head[u] = Top++;
}

void Init_head_Top(int n)
{
    memset(head,-1,sizeof(int)*(n+2));
    Top = 0;
}

int dp[MAXN];

int ans[MAXN][MAXN];

int root[MAXN];

int Top_Root;

int price[MAXN];

void dfs(int s,int m)
{
    ans[s][1] = price[s];

    for(int p = head[s] ; p != -1; p = edge[p].next)
    {
        dfs(edge[p].v,m);

        for(int i = m;i >= 0; --i)
        {
            for(int j = m-i;j >= 1; --j)
            {
                if(ans[s][i] != -1 && ans[s][i+j] < ans[s][i] + ans[edge[p].v][j])
                    ans[s][i+j] = ans[s][i] + ans[edge[p].v][j];
            }
        }

    }
}

int main()
{
    int n,m;

    int i,j,k,v;

    while(scanf("%d %d",&n,&m) && (n||m))
    {
        Init_head_Top(n);

        Top_Root = 0;

        memset(dp,-1,sizeof(dp));
        memset(ans,-1,sizeof(ans));

        for(i = 1; i <= n; ++i)
        {
            scanf("%d %d",&v,&price[i]);
            if(v)
                Link(v,i);
            else
                root[Top_Root++] = i;
        }

        for(i = 0; i < Top_Root; ++i)
        {
            dfs(root[i],m);
        }

        dp[0] = 0;


        for(j = 0; j < Top_Root; ++j)
        {
            for(i = m;i >= 0; --i)
            {
                if(dp[i] != -1)
                {
                    for(k = m-i;k >= 1; --k)
                    {
                        if(ans[root[j]][k] != -1 && dp[i] != -1 && dp[i+k] < dp[i] + ans[root[j]][k])
                            dp[i+k] = dp[i] + ans[root[j]][k];
                    }
                }
            }
        }



//        for(i = 1; i <= m; ++i)
//        {
//           // printf("cost = %2d w = %2d\n",i,dp[i]);
//        }
//
//        for(i = 1; i <= n; ++i)
//        {
//            for(j = 1; j <= m; ++j)
//            {
//                //printf("%2d ",ans[i][j]);
//
//            }
//           // puts("");
//        }

        int Max = dp[1];

        for(i = 1; i <= m ; ++i)
            Max = max(Max,dp[i]);
        printf("%d\n",Max);
    }

    return 0;
}