前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >10153. 「一本通 5.2 例 1」二叉苹果树

10153. 「一本通 5.2 例 1」二叉苹果树

作者头像
yzxoi
发布2022-09-19 12:14:02
2830
发布2022-09-19 12:14:02
举报
文章被收录于专栏:OI

10153. 「一本通 5.2 例 1」二叉苹果树

题意

有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 N 个节点,标号 1N,树根编号一定为 1

我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。

思路

表示以i为根节点,保留j个节点的最大苹果数量

f[i][j]=max{f[l[i]][k]+f[r[i]][j-k-1]+a[i]}(0<=k<=j-1)
f[i][j]=0(0<i<=n,0<=j<=Q+1)
f[i][j]=ai
Answer:f[1][Q+1]
代码语言:javascript
复制
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
    char ch=getchar();ll res=0,f=1;
    while(ch<'0'ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
    return res*f;
}
inline void write(ll x){
    if(x<0) putchar('-'),x=-x;
    if(x<10) putchar(x+'0');
    else{
        write(x/10);
        putchar(x%10+'0');
    }
}
ll n,Q,f[110][110],a[110],l[110],r[110],mp[110][110];
void MakeTree(int x){
    for(int i=1;i<=n;i++){
        if(mp[x][i]!=-1){
            l[x]=i;a[i]=mp[x][i];
            mp[x][i]=mp[i][x]=-1;
            MakeTree(i);
            break; 
        }
    }//Make Left Son
    for(int i=1;i<=n;i++){
        if(mp[x][i]!=-1){
            r[x]=i;a[i]=mp[x][i];
            mp[x][i]=mp[i][x]=-1;
            MakeTree(i);
            break;
        }
    }//Make Right Son
}
int DP(int x,int j){

    if(j==0){f[x][j]=0;return 0;}
    if((!l[x])&&(!r[x])){f[x][j]=a[x];return a[x];}
    if(f[x][j]>0) return f[x][j];
    for(int k=0;k<j;k++) f[x][j]=max(f[x][j],DP(l[x],k)+DP(r[x],j-k-1)+a[x]);
    return f[x][j];
}
int main(){
    n=read();Q=read();Q++;
    memset(mp,-1,sizeof(mp));
    for(int i=1;i<=n-1;i++){
        int x=read(),y=read(),z=read();
        mp[y][x]=mp[x][y]=z;
    }
    MakeTree(1);
    write(DP(1,Q));putchar('\n');
    /*
    cout<<"-----------------------------------"<<endl;
    for(int i=1;i<=n;i++){
        cout<<"Node "<<i<<":\n";
        cout<<"Left Son:"<<l[i]<<" Right Son:"<<r[i]<<endl;
        cout<<"Val:"<<a[i]<<endl;
        cout<<"DP :\n";
        for(int j=0;j<=Q;j++){
            cout<<"Has "<<j<<":"<<f[i][j]<<endl;
        }
        cout<<endl;
    } 
    */
    return 0;
}
//设f[i][j]表示以i为根节点,保留j个节点的最大苹果数量
//f[i][j]=max{f[l[i]][k]+f[r[i]][j-k-1]+a[i]}(0<=k<=j-1) 
//f[i][j]=0(0<i<=n,0<=j<=Q+1)
//f[i][j]=a[i](j!=0&&l[i]==0&&r[i]==0)
//Answer:f[1][Q+1]
/*
Sample Input:
5 2
1 3 1
1 4 10
2 3 20
3 5 20
Sample Output:
21
*/
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-02-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 10153. 「一本通 5.2 例 1」二叉苹果树
    • 题意
      • 思路
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档