codevs愚蠢的矿工(树形DP)

本文介绍了一种将多叉树问题转化为二叉树问题的方法,并通过树形DP解决人员分配问题。该方法首先将多叉树转化为二叉树形式,再利用记忆化递归进行动态规划求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
树形DP 
根节点一定有人 然后 剩下的人没到每个孩子去
因为孩子数可能很多 不好枚举 所以转二叉树 分两部分 O(sum)就可以了
当然 转二叉树候必须顾及原来树的一些性质 如不能只选左孩子
转化好了之后就是DP了
写的记忆化 递归每个节点 枚举分给左右孩子的人数  
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int n,m,son[maxn][3];
int f[maxn][maxn],a[maxn],ans;
int DP(int k,int sum)//到节点k时 还剩sum个人没有用 
{
    int i,maxx=0;
    if(f[k][sum]!=0)return f[k][sum];//记忆化 
    if(k==0||sum==0)return 0;//剪枝 
    f[k][sum]=a[k];//先整一个人在k处 
    for(i=1;i<=sum;i++)//枚举给左孩子多少人 i-1 
      {
          if(DP(son[k][2],i-1)+a[k]+DP(son[k][1],sum-i)>maxx)
          maxx=DP(son[k][2],i-1)+a[k]+DP(son[k][1],sum-i);
        if(DP(son[k][2],i)>maxx)maxx=DP(son[k][2],sum);//特殊情况 不要k 只要右孩子
        //因为这是多叉树转化来的 所以可以实现相反的 不能只要左孩子 因为左孩子和k连在一起 
      }
    if(f[k][sum]<maxx)
      f[k][sum]=maxx;
    return f[k][sum];
}
int main()
{
    cin>>n>>m;
    int i,x,y;
    for(i=1;i<=n;i++)cin>>a[i];
    for(i=1;i<=n;i++)
      {
          cin>>x>>y;
          if(son[x][1]==0)son[x][1]=y;
          else 
            {
              int fa=son[x][1];
              while(son[fa][2])fa=son[fa][2];
              son[fa][2]=y;
            }
      }
    ans=DP(son[0][1],m);
    cout<<ans;
    return 0;
}
 

 

转载于:https://www.cnblogs.com/yanlifneg/p/5432398.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值