现在的位置: 首页 > 综合 > 正文

POJ – 1155 (树形dp)

2019年04月03日 ⁄ 综合 ⁄ 共 1379字 ⁄ 字号 评论关闭

首先,这道题目参考别人题解,因为一直认为这样做会超时;

    以d[ i ] [ j ] 代表i节点为 服务器或 听众满足j个人的需求的最大收入;

  状态转移很明显 d[ i ] [ j ]  = max( d[ i ] [j ] , d[ i ][ j-k ]+d[ one_son ][ k ] - fee(fee为连通i和one_son这条边的花费)  );

  直接动归该方程是不可行的因为,在计算d[ i  ][ j - k ]时,还会重新利用one_son,而因为d [ i ][ j ]已经对son节点做出选k个的决断;这样会构成选取的重复;

  解决这个问题可以从一出发先解决子问题;然后集中精力解决该层的问题;对于这一层只要对每个孩子逐一判断,然后刷表解决;

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf  = 10000000;
const int maxn = 3100;
struct node{
   int to,val,next;
}tree[maxn];
int head[maxn],d[maxn][maxn],temp[maxn],n,m,len,fee[maxn],num[maxn];
void init(){
   memset(head,-1,sizeof(head));
   memset(num,0,sizeof(num));
   len = 0;
}
void add_eadge(int x,int y,int v){
   tree[len].to=y;
   tree[len].val=v;
   tree[len].next=head[x];
   head[x]=len++;
}
void dfs(int root){
    if(root>n-m){
          d[root][1]=fee[root];
          num[root] = 1;
          return ;
    }
    for(int i=head[root];i!=-1;i=tree[i].next){
       int p = tree[i].to;
       dfs(p);
       for(int j=0;j<=num[root];j++)
           temp[j]=d[root][j];
       for(int j=0;j<=num[root];j++)
           for(int k=1;k<=num[p];k++){
              d[root][k+j] = max(d[root][k+j],temp[j]+d[p][k]-tree[i].val);
       }
       num[root]+=num[p];
    }
}
int main()
{
    while(scanf("%d %d",&n,&m)==2){
         init();
         for(int i=1;i<=n-m;i++){
              int x,y,z;
              scanf("%d",&x);
              for(int j=1;j<=x;j++){
                  scanf("%d %d",&y,&z);
                  add_eadge(i,y,z);
              }
         }
         for(int i=n-m+1;i<=n;i++){
              int x;
              scanf("%d",&x);
              fee[i] = x;
         }
         for(int i=0;i<=n;i++){
             for(int j=0;j<=m;j++)
                d[i][j] = -inf;
             d[i][0] = 0;
         }
         dfs(1);
         int res = 0;
         for(int i=m;i>=0;i--){
              if(d[1][i]>=0){
                res = i; break;
              }
         }
         printf("%d\n",res);
    }
    return 0;
}

  

抱歉!评论已关闭.