P1040 [NOIP2003 提高组] 加分二叉树

news/2024/10/18 9:20:21/

题目描述

设一个 �n 个节点的二叉树 treetree 的中序遍历为(1,2,3,…,�)(1,2,3,…,n),其中数字 1,2,3,…,�1,2,3,…,n 为节点编号。每个节点都有一个分数(均为正整数),记第 �i 个节点的分数为 ��di​,treetree 及它的每个子树都有一个加分,任一棵子树 subtreesubtree(也包含 treetree 本身)的加分计算方法如下:

subtreesubtree 的左子树的加分 ×× subtreesubtree 的右子树的加分 ++ subtreesubtree 的根的分数。

若某个子树为空,规定其加分为 11,叶子的加分就是叶节点本身的分数。不考虑它的空子树。

试求一棵符合中序遍历为 (1,2,3,…,�)(1,2,3,…,n) 且加分最高的二叉树 treetree。要求输出

  1. treetree 的最高加分。

  2. treetree 的前序遍历。

输入格式

第 11 行 11 个整数 �n,为节点个数。

第 22 行 �n 个用空格隔开的整数,为每个节点的分数

输出格式

第 11 行 11 个整数,为最高加分(���≤4,000,000,000Ans≤4,000,000,000)。

第 22 行 �n 个用空格隔开的整数,为该树的前序遍历。

输入输出样例

输入 #1复制

5
5 7 1 2 10

输出 #1复制

145
3 1 2 4 5

说明/提示

数据规模与约定

对于全部的测试点,保证 1≤�<301≤n<30,节点的分数是小于 100100 的正整数,答案不超过 4×1094×109。

一道入门的区间dp,当然,根据写法不同你还可以把它归类为树形dp或者记忆化搜索,其实都无所谓啦。
作为一道入门题,我们完全可以“显然”地做出来,但是在这里还是想和大家回顾下动态规划以及区间动规。

Q:dp特点是什么?
A:dp把原问题视作若干个重叠的子问题的逐层递进,每个子问题的求解过程都会构成一个“阶段”,在完成一个阶段后,才会执行下一个阶段。
Q:dp要满足无后效性,什么叫无后效性?
A:已经求解的子问题不受后续阶段的影响。

有人觉得dp很抽象,那是因为没有一步一步来想,直接听别人的结论,我们在这里以这道题为例,一步一步来推导。

首先,我们要做的就是设计状态,其实就是设计dp数组的含义,它要满足无后效性。
关注这个 左子树*右子树+根 我只要知道左子树分数和右子树分数和根的分数(已给出),不就可以了吗?管他子树长什么样!
所以,我们�f数组存的就是最大分数,怎么存呢?
我们发现:子树是一个或多个节点的集合。
那么我们可不可以开一个�[�][�]f[i][j]来表示节点i到节点j成树的最大加分呢?可以先保留这个想法(毕竟暂时也想不到更好的了)。

如果这样话,我们就来设计状态转移方程。
按照刚刚的设计来说的话,我们的答案就是�[1][�]f[1][n]了,那么我们可以从小的子树开始,也就是len,区间长度。有了区间长度我们就要枚举区间起点,i为区间起点,然后就可以算出区间终点j。
通过加分二叉树的式子我们可以知道,二叉树的分取决于谁是根,于是我们就在区间内枚举根k。
特别的,�[�][�]=�[�]f[i][i]=a[i]其中a[i]为第i个节点的分数。
因为是要求最大值,所以我们就可以设计出

�[�][�]=���(�[�][�−1]∗�[�+1][�]+�[�][�])f[i][j]=MAX(f[i][k−1]∗f[k+1][j]+f[k][k])

于是乎,我们就自己设计出了一个dp过程,因为是顺着来的,所以很少有不成立的。

至于输出前序遍历,我们再设计一个状态����[�][�]root[i][j]来表示节点i到节点j成树的最大加分所选的根节点。
所以我们按照根−>左−>右根−>左−>右的顺序递归输出即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 50;
typedef long long ll;
ll n;
ll f[MAXN][MAXN], root[MAXN][MAXN];void print(ll l, ll r) {if (l > r)return;printf("%lld ", root[l][r]);if (l == r)return;print(l, root[l][r] - 1);print(root[l][r]+1,r);
}int main() {scanf("%lld", &n);for (int i = 1; i <= n; i++)scanf("%lld", &f[i][i]),f[i][i-1]=1, root[i][i] = i;for (int len = 1; len < n; ++len) {for (int i = 1; i + len <= n; ++i) {int j = i + len;f[i][j] = f[i + 1][j] + f[i][i];//默认它的左子树为空,如果有的话,这肯定不是最优解root[i][j] = i;//默认从起点选根for (int k = i + 1; k < j; ++k) {if (f[i][j] < f[i][k - 1] * f[k + 1][j] + f[k][k]) {f[i][j] = f[i][k - 1] * f[k + 1][j] + f[k][k];root[i][j] = k;}}}}cout << f[1][n] << endl;print(1, n);return 0;
}

http://www.ppmy.cn/news/51102.html

相关文章

ch6_1计算机中运算方法

计算机中数的表示计算机的运算方法运算器的设计 参考教材 本章内容主要介绍&#xff0c;计算机中的运算方法 无符号数和有符号数数的定点表示和浮点表示定点运算浮点四则运算算术逻辑单元 1. 无符号数和有符号数 1.1 无符号数 1.2 有符号数 计算机中&#xff0c; 小数点…

Java文件字符流和字节流中的实战

文件输入输出流 文件内容操作与实战字符流ReaderWriter 字节流inputStreamOutputStream实战&#x1f4aa; 文件内容操作与实战 文件的分类上一篇文章&#xff08;文件对象处理&#xff09;已经和大家讲解过了。本章主要文件主要针对于对文件内容的操作展开讲解&#xff0c;文件…

系统分析师之信息化技术(十一)

目录 一、企业信息化概述 1.1 信息系统的基本概念 1.1.1 什么是信息 1.1.2 什么是信息化 1.1.3 信息系统分类 二、企业信息化规划 2.1 信息化战略体系 2.2 企业战略与信息化战略集成方法 三、信息系统开发方法 3.1 信息系统开发方法 3.2 系统建模 四、信息系统战略…

如何用Python搭建HTTP服务器,并实现远程访问和下载?

Python是编程语言中的热门语言&#xff0c;具有语法简单、语句清晰的特点。如果你不擅长编程&#xff0c;学习Python是一个不错的选择&#xff0c;初学者在学习阶段可以较为轻松地理解编程对象和思维方法。对于小白用户来说,它具有强大且丰富的库,封装后可以轻松调用,因此也更受…

走进社区客户端测试 | 得物技术

0.引言 社区 C 端质量体系建设思考&#xff1f; 询问一下 ChatGPT 1、关于社区客户端 1.1 社区端上功能 得物首页 搜索、发布、关注流、推荐流、沉浸式单列流、活动 tab、其他二级频道 tab 动态详情页 图文、视频、专栏、点评 私域 个人/他人主页、通讯录好友、微博好友…

ChatGPT的开源平替,终于来了!

最近这段时间&#xff0c;一个号称全球最大ChatGPT开源平替项目Open Assistant引起了大家的注意。 这不最近还登上了GitHub的Trending热榜。 https://github.com/LAION-AI/Open-Assistant 根据官方的介绍&#xff0c;Open Assistant也是一个对话式的大型语言模型项目&#xff…

DX云音乐(安卓)

首先&#xff0c;软件安装好不用注册登录就可以直接使用&#xff0c;在首页这里有很多推荐的热门歌单&#xff0c;比如&#xff0c;有年度热门的DJ歌曲&#xff0c;有抖音热门DJ&#xff0c;有各种跨年晚会&#xff0c;有运动必备的DGM&#xff0c;有90后的经典旋律等等。 还有…

资本观望,大厂入局,海外大模型血脉压制……国内AIGC创业者的机会在哪里?...

图片来源&#xff1a;由无界 AI生成 A股AI概念股直线式拉涨&#xff0c;技术大牛带资进组分分钟成数十亿人民币独角兽&#xff0c;互联网巨头争抢着入局&#xff0c;政府各类扶持政策持续出台&#xff0c;媒体动不动就是万亿风口&#xff0c;500万年薪难招AIGC大牛……2022年以…