【算法•日更•第十期】树型动态规划&区间动态规划:加分二叉树题解
废话不多说,直接上题:
1580:加分二叉树
时间限制: 1000 ms 内存限制: 524288 KB
提交数: 121 通过数: 91
【题目描述】
原题来自:NOIP 2003
设一个 n 个节点的二叉树 tree 的中序遍历为 (1,2,3,⋯,n),其中数字 1,2,3,⋯,n 为节点编号。每个节点都有一个分数(均为正整数),记第 i 个节点的分数为 di ,tree 及它的每个子树都有一个加分,任一棵子树 subtree(也包含 tree 本身)的加分计算方法如下:
记 subtree 的左子树加分为 l,右子树加分为 r,subtree 的根的分数为 a,则 subtree 的加分为:
l×r+a
若某个子树为空,规定其加分为 1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。
试求一棵符合中序遍历为 (1,2,3,⋯,n) 且加分最高的二叉树 tree。
要求输出:
1、tree 的最高加分;
2、tree 的前序遍历。
【输入】
第一行一个整数 n 表示节点个数;
第二行 n 个空格隔开的整数,表示各节点的分数。
【输出】
第一行一个整数,为最高加分 b;
第二行 n 个用空格隔开的整数,为该树的前序遍历。
【输入样例】
5
5 7 1 2 10
【输出样例】
145
3 1 2 4 5
【提示】
数据范围与提示:
对于 100% 的数据,n<30,b<100,结果不超过 4×109 。
【来源】
这道题在信息奥赛一本通oj上被归类为树型动态规划,其实并不是,确实有树的数据结构要用到,但是更多需要的是区间动态规划的技巧。如果你不会区间动态规划,请戳这里学习区间动态规划。
首先,我们把这道题分成两个部分,分别是求最高加分和树的先序遍历,先来说最高加分怎么办:
先思考一下,题目中给出的顺序(中序遍历)有什么用?中序遍历的顺序是左子树 -> 根节点 -> 右子树,那么我们不妨枚举根节点的位置,那么根节点左边的就是左子树,右边的就是右子树,然后继续在左右子树中以同样的方法枚举根节点……直到分成叶子结点,返回该节点的分数就可以了。这样是什么,这不就是递归吗?所以我们这里采用记忆化搜索的形式来写。
那么我们就可以用f[i][j]来表示i到j区间内的最大加分,状态转移方程就很明了了:f[i][j]=max{f[i][k-1]+f[k+1][j]+a[i]}。
不过需要注意一点,可能会出现一些越界(其实是空树)情况,例如i>j时,记得返回1。
然后,我们来考虑怎么输出先序遍历,我们可以在执行上面的动态规划的过程中记录下一个root二维数组,root[i][j]表示i到j区间内选择的最优根节点编号,方便于输出先序遍历结果。最后只要按照先序遍历的顺序遍历就行了,碰到叶子节点时直接输出。
好了,代码如下:
#include<iostream>
using namespace std;
int f[][],a[],tree[],root[][],cnt,mid,n,ans;
int dp(int i,int j)//动态规划
{
if(i==j) return a[i];//碰到叶子结点直接返回
if(i>j) return ;//注意空树(不存在左子树或右子树或都不存在)的情况
if(f[i][j]) return f[i][j];//记忆化
for(int k=i;k<=j;k++)
{
int x=dp(i,k-)*dp(k+,j)+a[k];//状态转移方程
if(f[i][j]<x)
{
f[i][j]=x;
root[i][j]=k;//记录i~j区间的根节点
}
}
return f[i][j];
}
void print(int i,int j)
{
if(i>j) return;//避免空树
if(i==j)//叶节点直接输出
{
cout<<i<<" ";
return;
}
cout<<root[i][j]<<" ";//根
print(i,root[i][j]-);//左子树
print(root[i][j]+,j);//右子树
}
int main()
{
cin>>n;
for(int i=;i<=n;i++)
cin>>a[i];
cout<<dp(,n)<<endl;
print(,n);
return ;
}
【算法•日更•第十期】树型动态规划&区间动态规划:加分二叉树题解的更多相关文章
- 【算法•日更•第十九期】动态规划:RMQ问题
▎前言 首先先来说一下RMB是什么,当然是人民币啦. 今天我们要学的这个东西不一般,叫做RMQ问题,那么它和RMB有什么关系呢?待小编细细说来. ▎前置技能:动态规划 不会的同志请戳这里迅速了解动态规 ...
- 【算法•日更•第二十八期】图论:强连通+Tarjan算法(一)
▎前言 一直都想学习这个东西,以为很难,结果发现也不过如此. 只要会些图论的基础就可以了. ▎强连通 ☞『定义』 既然叫强连通,那么一定具有很强的连通性. 强连通:就是指在一个有向图中,两个顶点可以互 ...
- 【算法•日更•第十二期】信息奥赛一本通1585:【例 1】Amount of Degrees题解
废话不多说,直接上题: 1585: [例 1]Amount of Degrees 时间限制: 1000 ms 内存限制: 524288 KB提交数: 130 通过数: 68 [ ...
- 【算法•日更•第六期】头脑风暴:洛谷P1528 切蛋糕题解
▎(一个没有用处的)前言 为什么这次题解特意写明题号呢?因为我发现了这样的事情: 所以不要混了,想看P1714题解的同志们可以圆润的滚开了. 好了,不说没用的了,切入正题: ▎题目 题目及测评链接:戳 ...
- 【算法•日更•第二十三期】数据结构:two-pointer(尺取法)&莫队
▎引入 ☞『例题』 一道十分easy的题: 洛谷P1638 长度为n的序列,m种数 找一个最短区间,使得所有数出现一遍 n≤1e6 ,m≤2e3. ☞『分析』 这道题非常的简单,但是如果不会two-p ...
- 【算法•日更•第二十七期】基础python
▎前言 看到这个题目,你一定会很好奇,为什么学打NOIP的要学习python?其实python对我们是很有用的! NOIP虽然不支持使用python提交代码,但是在NOILinux上天生自带pytho ...
- 【算法•日更•第五十四期】知识扫盲:什么是operator?
▎前言 这个东西和迭代器长的很像,但是比迭代器常见的多. 今天就来浅谈operator. ▎定义 operator是C#.C++和pascal的关键字,它和运算符一起使用,表示一个运算符函数,理解时应 ...
- 【算法•日更•第三十九期】迭代加深搜索:洛谷SP7579 YOKOF - Power Calculus 题解
废话不多说,直接上题: SP7579 YOKOF - Power Calculus 题意翻译 (略过没有营养的题干) 题目大意: 给出正整数n,若只能使用乘法或除法,输出使x经过运算(自己乘或除自己, ...
- 【算法•日更•第三十五期】FF算法优化:EK算法
▎写在前面 FF算法传送门 之前我们已经学过了FF算法(全称Ford-Fulkerson算法)来找最大流,但是这种算法仍有诸多不对的地方. 其实这种算法存在着严重的效率的问题,请看下面的图: 以这个图 ...
随机推荐
- 题解 洛谷 P3185 【[HNOI2007]分裂游戏】
首先可以发现,当所有巧克力豆在最后一个瓶子中时,就无法再操作了,此时为必败状态. 注意到,对于每个瓶子里的巧克力豆,是可以在模\(2\)的意义下去考虑的,因为后手可以模仿先手的操作,所以就将巧克力豆个 ...
- Kafka 入门(一)--安装配置和 kafka-python 调用
一.Kafka 简介 1.基本概念 Kafka 是一个分布式的基于发布/订阅消息系统,主要应用于大数据实时处理领域,其官网是:http://kafka.apache.org/.Kafka 是一个分布式 ...
- 数字货币交易所(火币为例)如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器?
一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接 数字货币交易所(火币为例)如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器? 二次验证码小程序于谷歌身份验证器APP的优 ...
- 学习2周C++的收获
学习2周C++的收获 首先,C++是一种实用性很强的程序设计语言.它使用起来灵活.方便,运算符丰富,有结构化的层次…… 那么,我学习这个语言主要是为了参加信息学奥林匹克竞赛,这不仅要熟练地掌握一门语言 ...
- WARNING: 'aclocal-1.14' is missing on your system.问题解决记录
在编译LXC时,遇到一个问题,提示 'aclocal-1.14'缺失.如下:WARNING: 'aclocal-1.14' is missing on your system. You should ...
- getprop与dumpsys命令
拿到Android手机以后, 想查看一些手机信息. 其实Android获取手机信息就是两个命令, 一个是getprop 一个是dumpsys. dumpsys iphonesubinfo Phone ...
- variable ans might not have been initialized 报错,以及初始化注意点
他是说你没有初始化而已,一般只是个warning,如果是在不能跑,那就给他初始化一下. 注意,初始化可不是任意值哈! 就比如如果要算阶乘,你初始化就不能为0. 还有如果是比较大小这类,就不要把初始化统 ...
- 7-Pandas之索引调整方法
一.调整索引.修改列标签 1.调整索引的两种情况: 重新索引 设置新的索引 (1)重新索引 在Pandas对象中,其实索引也是一个对象,所以可对其进行修改. 例如:df.index=['a','b', ...
- Python os.tcsetpgrp() 方法
概述 os.tcsetpgrp() 方法用于设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg.高佣联盟 www.cgewang.com 语法 tcsetpgrp()方 ...
- 【小白学AI】八种应对样本不均衡的策略
文章来自:微信公众号[机器学习炼丹术] 目录 1 什么是非均衡 2 8种解决办法 2.1 重采样(四种方法) 2.2 调整损失函数 2.3 异常值检测框架 2.4 二分类变成多分类 2.5 EasyE ...