码迷,mamicode.com
首页 > 其他好文 > 详细

树形dp入门-加分二叉树(luogu1040)

时间:2018-02-13 10:28:08      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:节点   技术分享   log   解决问题   遍历   oid   com   需要   最大值   

今天学习了树形dp,确实,感受到了深深的压力...一会还得去写选课那道题。。。

先看题目:

技术分享图片

技术分享图片

首先我们看到关键字:中序遍历。既然已经给出我们分数的算法,所以我们就可以通过枚举根节点来解决问题。在每一个根节点下求最优解,且记录下每一个根节点,就恰好能完成两个任务。即我们需要写两个子程序。

看代码:(请勿直接复制粘贴)

#include <stdio.h>
int n,point[32],f[32][32],mumber[32][32];
long long tree(int left,int right)
{
    if(left>right) return 1;//题目中有提到,如果left>right即是一个空树,加分为1
    if(left==right) return point[left];//即为根节点,就加上该点的分数
    if(f[left][right]) return f[left][right];//记忆化搜索,如果没有记忆化很可能会TLE上几个点
    long long MAX=0,maxnow=0;//定初值
    int kkk=0;
    for(int k=left;k<=right;k++)//枚举根节点
    {
        maxnow=point[k]+tree(left,k-1)*tree(k+1,right);//计算当前根节点下的分数的最优解
        if(maxnow>MAX)
        {
            MAX=maxnow;//打擂台
            kkk=k;//记录此时的根节点
        }
        f[left][right]=MAX;
        mumber[left][right]=kkk;
    }
    return MAX;//返回最大值,第一个问题解决。
}
void print(int l,int r)
{
    if(l>r) return ;//终止条件
    if(l==r)
    {
        printf("%d ",l);//根节点
        return ;
    }
    int kkk=mumber[l][r];
    printf("%lld ",kkk);//输出该节点的编号
    print(l,kkk-1);//
    print(kkk+1,r);//前序遍历
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&point[i]);//读入分数
    printf("%d\n",tree(1,n));//输出最优解(返回的值)
    print(1,n);
    return 0;
}

加油吧。

树形dp入门-加分二叉树(luogu1040)

标签:节点   技术分享   log   解决问题   遍历   oid   com   需要   最大值   

原文地址:https://www.cnblogs.com/noipzylfromxj/p/8445912.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!