poj 1155 树形背包

http://blog.csdn.net/libin56842/article/details/9908199

树形背包:

首先是建树,每个结构体为一个节点,包括下一个点序号,值,和next。

tree[ptr]会保存所有的节点序列,而head数组则是保存每个节点的最后一个子节点序列中的位置,next则是保存上一个子节点在序列中的位置,若没有则为-1。

遍历时从i=head[root]出发,到i=-1结束,不断往子节点遍历,同一层之间用next遍历,就可以遍历树的所有节点。

树状dp。由于求的是最多多少用户,那么我们可以把用户个数当成一个状态。dp[i][j]代表i节点为根节点的子树j个用户的时候最大剩余费用。

     则dp[i][j] = max(dp[i][j], dp[i][k]+dp[son][j-k]-w[i][son]);

注意两点,第一点是上面式子中的dp[i][k]必须先用一个tem[MAX]数组提取出来,因为在计算的过程中会相互影响。第二点是价值可能是负值,所以dp初始化的时候要初始化为负的最大值。

#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 1010
#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,val,next;
}tree[9005];

int head[3005],dp[3005][3005],num[3005],tem[3005],ptr=1;


void add(int x,int y,int val)
{
    tree[ptr].y = y;
    tree[ptr].val = val;
    tree[ptr].next = head[x];
    head[x] = ptr++;
}

void dfs(int root)
{
    int i,j,k;
    for(i=head[root]; i!=-1; i=tree[i].next)
    {
        int p = tree[i].y;
        dfs(p);

        for(j=0;j<=num[root];j++)
            tem[j] = dp[root][j];

        for(j=0;j<=num[root];j++)
        {
            for(k=1;k<=num[p];k++)
            {
                dp[root][k+j] = max(dp[root][j+k],tem[j]+dp[p][k]-tree[i].val);
                //pf("%d %d %d %d
",root,j,k,dp[root][j+k]);
            }
        }
        num[root]+=num[p];
    }
}

int main()
{
    int i,j,k,a,b;
    while(~sf("%d%d",&n,&m) && m+n)
    {
        mem(head,-1);
        for(i=1;i<=n-m;i++)
        {
            sf("%d",&k);
            num[i] = 0;
            for(j=0;j<k;j++)
            {
                sf("%d%d",&a,&b);
                add(i,a,b);
            }
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
                dp[i][j] = -10000000;
        }

        for(i=n-m+1;i<=n;i++)
        {
            num[i] = 1;
            sf("%d",&dp[i][1]);
        }
        dfs(1);
        for(i=m;i>=0;i--)
        {
            if(dp[1][i]>=0)
            {
                pf("%d
",i);
                break;
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qlky/p/5650783.html