POJ 1155 - TELE 树形DP(泛化背包转移)..

来源:互联网 发布:python 测试框架 编辑:程序博客网 时间:2024/06/06 04:11

    dp[x][y]代表以x为根的子树..连接了y个终端用户(叶子)..所能获得的最大收益...

    dp[x][ ]可以看成当根为x时..有个背包空间为0~m...每个空间上记录了到到达这个空间的最大收益..

    典型的泛化背包问题... 


Program:

#include<iostream>#include<stdio.h>#include<string.h>#include<set>#include<ctime>#include<algorithm>#include<queue>#include<cmath>#include<map>#define oo 100000007#define ll long long#define pi acos(-1.0)#define MAXN 3005using namespace std;struct node{      int x,y,c,next;}line[MAXN];int n,m,_next[MAXN],v[MAXN],dp[MAXN][MAXN],SubNum[MAXN];void addline(int x,int y,int c,int m){      line[m].next=_next[x],_next[x]=m;      line[m].x=x,line[m].y=y,line[m].c=c;      return;}void dfs(int x){      int k=_next[x];       SubNum[x]=dp[x][0]=0;      if (!k) dp[x][1]=v[x],SubNum[x]=1;      else      while (k)      {            int i,j,y=line[k].y;            dfs(y);            SubNum[x]+=SubNum[line[k].y];            for (i=SubNum[x];i>=1;i--)               for (j=0;j<=SubNum[y] && j<=i;j++)                  dp[x][i]=max(dp[x][i],dp[x][i-j]+dp[y][j]+line[k].c); //泛化背包转移            k=line[k].next;      }      return;}int main(){      int i,num,t;       while (~scanf("%d%d",&n,&m))      {             num=0;             memset(_next,0,sizeof(_next));             memset(dp,-0x1f,sizeof(dp));             memset(v,0,sizeof(v));             memset(SubNum,0,sizeof(SubNum));             for (i=1;i<=n-m;i++)             {                   scanf("%d",&t);                   while (t--)                   {                         int A,C;                         scanf("%d%d",&A,&C);                         addline(i,A,-C,++num);                   }              }             for (i=n-m+1;i<=n;i++) scanf("%d",&v[i]);             dfs(1);             for (i=m;i>=1;i--)               if (dp[1][i]>=0) break;             printf("%d\n",i);      }      return 0;}


原创粉丝点击