HDU 1561 The more, The Better - 依赖背包+树形dp基础

题意: 给一个树形结构,问最多拿max个城市 ,能获得的最大价值多少,拿下面的一定要先拿上面的。
解题思路:
定义状态dp[i][j] : 当前i节点及其子树下最多选择j个城市的最大值为dp[i][j];
我们考虑到特殊状态:i节点下没有孩子那么dp[i][2,3,4,5...]均为-1(因为多选总比少选好,并且选择完后城市总是有剩余)


1. 判断当前节点P有没有孩子,如果有则令当前节点为P重复(1)操作,如果没有则到(2)操作;
2. 将当前节点P的状态更新到期父节点上,
更新操作为dp[P'father][i] = max(dp[P'father][i], dp[P'father][j]+dp[P][k])    (j + k = i ,j>0,k>0,2<=i<=max_cost,对于每一个i遍历每一种(j,k)组合)
这里的dp[P'father][j] j个城市一定是没有包括P城市的其他j个城市的最大值 
直到遍历到root节点即可(dp[0][i])
3.输出dp[0][max_cost]
max_cost 为题目中所给出的最多取几个城市


7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
[i]:v 表示 第i个节点的价值为v; [0]root没有价值相当于[0]:0
                   [0]root
                 /         \
            [2]:1          [3]:4
         /    |   \   
   [1]:2   [4]:1   [7]:2
                  /     \

                [5]:1  [6]:6

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int INF=(1<<30);
const int M=200+10;
vector <int> list[M];
int dp[M][M];
int n,max_cost;
void dfs(int father){
   for(int i=0;i<list[father].size();i++){
     int child=list[father][i];
   if(list[child].size()>0)
        dfs(child);
   for(int j=max_cost;j>1;j--)
       for(int k=1;k<j;k++)
         dp[father][j]=max(dp[father][j],dp[father][k]+dp[child][j-k]);

   }
}
int main()
{
   while(cin>>n>>max_cost,n&&max_cost)
   {
       max_cost++;
       memset(dp,0,sizeof(dp));
       for(int i=1;i<=n;i++)
       {
           int a,b;
           cin>>a>>b;
           list[a].push_back(i);
           for(int j=1;j<=max_cost;j++)
            dp[i][j]=b;
       }
       dfs(0);
       for(int i=0;i<=n;i++)
        list[i].clear();
       cout<<dp[0][max_cost]<<endl;
   }
   return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值