NOIP2003提高组第二轮T3:加分二叉树

题目链接

[NOIP2003 提高组] 加分二叉树

题目描述

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

subtree \text{subtree} subtree 的左子树的加分 × \times × subtree \text{subtree} subtree 的右子树的加分 + + + subtree \text{subtree} subtree 的根的分数。

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

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

  1. tree \text{tree} tree 的最高加分。

  2. tree \text{tree} tree 的前序遍历。

输入格式

1 1 1 1 1 1 个整数 n n n,为节点个数。

2 2 2 n n n 个用空格隔开的整数,为每个节点的分数

输出格式

1 1 1 1 1 1 个整数,为最高加分( A n s ≤ 4 , 000 , 000 , 000 Ans \le 4,000,000,000 Ans4,000,000,000)。

2 2 2 n n n 个用空格隔开的整数,为该树的前序遍历。

样例 #1

样例输入 #1

5
5 7 1 2 10

样例输出 #1

145
3 1 2 4 5

提示

数据规模与约定

对于全部的测试点,保证 1 ≤ n < 30 1 \leq n< 30 1n<30,节点的分数是小于 100 100 100 的正整数,答案不超过 4 × 1 0 9 4 \times 10^9 4×109

算法思想

最高加分

根据题目描述:

  • 一棵二叉树的中序遍历为 ( 1 , 2 , 3 , … , n ) (1,2,3,\ldots,n) (1,2,3,,n)

在中序遍历中,一旦确定了根结点,那么左右子树的节点编号一定在根结点两侧,例如当根节点为 3 3 3时,那么左子树的结点编号为 1 , 2 1,2 1,2,右子树的结点编号为 4 , 5 , … , n 4,5,\ldots, n 4,5,,n,如下图所示:

在这里插入图片描述

  • 加分计算方法为左子树的加分 × \times × 右子树的加分 + + +根的分数。

求一棵符合中序遍历为 ( 1 , 2 , 3 , … , n ) (1,2,3,\ldots,n) (1,2,3,,n) 且加分最高的二叉树,就是求以根节点为中心,将左右两个区间(子树)合并在一起的最大值,因此可以使用区间型动态规划进行处理。

状态表示

f [ i , j ] f[i,j] f[i,j]表示二叉树中序遍历的节点编号在区间 [ i , j ] [i,j] [i,j]的最大加分分值。

状态计算

从最后一个合并位置,也就是根节点的位置可以将状态计算分为下面几种情况:

  • 根节点在 i i i位置,此时左子树为空,加分为 1 × 1\times 1×,得到的分数为 1 × f [ i + 1 ] [ j ] + w [ i ] 1\times f[i+1][j]+w[i] 1×f[i+1][j]+w[i]
  • 根节点在 i + 1 i+1 i+1位置,得到的分数为 f [ i ] [ i ] × f [ i + 2 ] [ j ] + w [ i + 1 ] f[i][i]\times f[i+2][j]+w[i+1] f[i][i]×f[i+2][j]+w[i+1]
  • 根节点在 k k k位置,得到的分数为 f [ i ] [ k − 1 ] × f [ k + 1 ] [ j ] + w [ k ] f[i][k-1]\times f[k+1][j]+w[k] f[i][k1]×f[k+1][j]+w[k]
  • 根节点在 j j j位置,此时右子树为空,加分为 1 × 1\times 1×,得到的分数为 f [ i ] [ j − 1 ] × 1 + w [ j ] f[i][j-1]\times 1+w[j] f[i][j1]×1+w[j]

这里 w [ i ] w[i] w[i]表示第 i i i个节点的分数。 f [ i ] [ j ] f[i][j] f[i][j]要取以上情况的最大值。

初始状态

  • 空树其加分为 1 1 1,也就是说 f [ i ] [ i − 1 ] = 1 f[i][i-1]=1 f[i][i1]=1(或者 f [ i + 1 ] [ i ] = 1 f[i+1][i]=1 f[i+1][i]=1
  • 如果区间只有一个节点,那么分值就是当前节点的分数,即 f [ i ] [ i ] = w [ i ] f[i][i]=w[i] f[i][i]=w[i]

时间复杂度

状态数为 n × n n\times n n×n,状态计算需要枚举根节点的位置 1 1 1 ~ n n n,时间复杂度为 O ( n 3 ) O(n^3) O(n3)

前序遍历

为了找到最大加分的前序遍历,就要在区间 [ i , j ] [i,j] [i,j]中找到一个根节点 k k k使得 f [ i ] [ k − 1 ] × f [ k + 1 ] [ j ] + w [ k ] f[i][k - 1]\times f[k+1][j]+w[k] f[i][k1]×f[k+1][j]+w[k]等于 f [ i ] [ j ] f[i][j] f[i][j]

对于前序遍历要先输出根节点 k k k,然后在递归遍历左子树( [ i , k − 1 ] [i,k-1] [i,k1])和右子树( [ k + 1 , j ] [k+1,j] [k+1,j])即可。

注意,如果 i i i j j j相等,说明是叶子节点,其子树的根节点就是自己。

代码实现

#include <iostream>
using namespace std;
const int N = 50;
int w[N], f[N][N];
int n;
//求区间[i,j]的前序遍历
void dfs(int i, int j)
{if(i > j) return; //空二叉树if(i == j) cout << i << " "; //叶子节点else{//枚举根节点for(int k = i; k <= j; k ++){//如果以k为根节点取得加分最大值if(f[i][j] == f[i][k - 1] * f[k + 1][j] + w[k]) {cout << k << " "; //输出根节点dfs(i, k - 1); //递归遍历左子树dfs(k + 1, j); //递归遍历右子树break;}}}
}int main()
{cin >> n;for(int i = 1; i <= n; i ++) cin >> w[i];//空树的加分为1for(int i = 1; i <= n + 1; i ++) f[i][i - 1] = 1;//枚举合并长度for(int len = 1; len <= n; len ++){//枚举开始位置for(int i = 1; i + len - 1 <= n; i ++){int j = i + len - 1; //结束位置if(len == 1) f[i][i] = w[i]; //初始状态else{//枚举其它根节点的位置for(int k = i; k <= j; k ++)f[i][j] = max(f[i][j], f[i][k - 1] * f[k + 1][j] + w[k]);}            }}cout << f[1][n] << '\n';dfs(1, n);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/164401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【视觉SLAM十四讲学习笔记】第三讲——Eigen库

专栏系列文章如下&#xff1a; 【视觉SLAM十四讲学习笔记】第一讲——SLAM介绍 【视觉SLAM十四讲学习笔记】第二讲——初识SLAM 【视觉SLAM十四讲学习笔记】第三讲——旋转矩阵 本章将介绍视觉SLAM的基本问题之一&#xff1a;如何描述刚体在三维空间中的运动&#xff1f; Eigen…

网工内推 | Base北京,国企网工运维,最高30k*14薪,IE认证优先

01 万方数据股份有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1.负责完成基础网络组网工作&#xff1b; 2.负责网络对象的访问控制及安全策略&#xff0c;配置VLan&#xff0c;黑白名单、地址转换、故障排查及网络安全监控工作&#xff1b; 3.负责对操作系…

Vue框架学习笔记——Vue实例中el和data的两种写法

文章目录 前文提要Vue实例的el第一种写法第二种写法小结 Vue实例中data第一种写法&#xff0c;对象式效果图片第二种写法&#xff0c;函数式效果图片小结 前文提要 本文仅做自己的学习记录&#xff0c;如有错误&#xff0c;请多谅解 Vue实例的el 第一种写法 <body><…

Python图片文件和base64编码互转

图片和base64编码互转 import base64 import cv2# 将图片base64字符串生成图片文件. def base64_to_img(base64_code,save_img_path):"""根据base64生成图片.:param base64_code: 图片的base64文件:param save_img_path: 生成的图片路径:returns: None"&q…

分布式锁之基于mysql实现分布式锁(四)

不管是jvm锁还是mysql锁&#xff0c;为了保证线程的并发安全&#xff0c;都提供了悲观独占排他锁。所以独占排他也是分布式锁的基本要求。 可以利用唯一键索引不能重复插入的特点实现。设计表如下&#xff1a; CREATE TABLE tb_lock (id bigint(20) NOT NULL AUTO_INCREMENT,…

(二)C语言之变量与算数运算表达式概述

C语言之变量与算数运算表达式概述 一、华氏温度与摄氏温度对照二、代码概述三、练习 一、华氏温度与摄氏温度对照 #include <stdio.h>/*当华氏温度为 0,20,40,...300时&#xff0c;打印出华氏温度与摄氏温度对照表华氏温度与摄氏温度 C(5/9)(̧F-32) 其中C表示摄氏温度&…

顺序栈和链栈

#include<iostream> using namespace std; #define MAXSIZE 100 typedef int SElemType; typedef struct { SElemType* base; SElemType* top; int stacksize; }SqStack;//顺序栈 //构造一个空栈 int InitStack(SqStack& s) { s.base new SElemType…

Django之中间件与CSRF_TOKEN

文章目录 一、什么是中间件二、中间件有什么用三、Django自定义中间件中间件中主要方法及作用创建自定义中间件的步骤&#xff1a;process_request与process_response方法process_view方法process_exceptionprocess_template_response&#xff08;不常用&#xff09; 四、CSRF_…

mysql latin-1报错解决

conn pymysql.connect(hostmeta_conf[host], usermeta_conf[user], passwordmeta_conf[password], portmeta_conf[port], charsetutf8) 光把表声明 ENGINEINNODB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_bin ROW_FORMATDYNAMIC 并不能解决这个报错,需要在创建mysql连接时候…

面试:RabbitMQ相关问题

文章目录 简单介绍RabbitMQRabbitMQ架构什么是 RabbitMQ&#xff1f;有什么显著的特点&#xff1f;RabbitMQ 有那些基本概念&#xff1f;RabbitMQ routing 路由模式消息怎么路由&#xff1f;RabbitMQ publish/subscribe 发布订阅(共享资源)能够在地理上分开的不同数据中心使用 …

vue2指令的使用和自定义指令

前言 个人认为vue的指令,对比react来说,给开发者节省了很大的学习成本。比如在react中,你想渲染一个列表,需要用Array.map的方法return<div>,而在vue中,一个简单的v-for就解决了问题。 在学习成本和入手体验上,vue的作者确实后来者居上,能让人更快的使用vue开发。不过也…

无边界电视点播TVbox壳+源

TBBox可以是个盒子也可以是软件 视频播放的困局新的改变TVBox apk更成熟的熊猫宝盒_3.10还有这个没测试恒星TV 写在最后 视频播放的困局 现在电视上几大平台看剧集都要充会员&#xff0c;而电脑上网页端有很多可以看的网页&#xff0c;只有 随便一搜就测出来&#xff0c;只是经…

数据安全第一:应对[[MyFile@waifu.club]].wis勒索病毒的实用建议与技巧

引言&#xff1a; 在当今数字化时代&#xff0c;[[MyFilewaifu.club]].wis、[[backupwaifu.club]].wis勒索病毒是一种恶意软件&#xff0c;其危害用户数据安全&#xff0c;通过加密文件并勒索赎金来获取经济利益。以下是对[[MyFilewaifu.club]].wis、[[backupwaifu.club]].wis…

PyTorch包

进入PyTorch的官网&#xff1a; pytorch GitHub 点击GitHub&#xff1a; 进入PyTorch的主目录&#xff1a; 进入Vision reference&#xff1a; detection&#xff1a; 这就是我们在训练过程中会使用到的文件了&#xff1a;

objdump反汇编文件解析

命令使用 objdump可以对可执行文件进行反汇编 其常用参数为: objdump -d <file(s)>: 将代码段反汇编&#xff1b;objdump -S <file(s)>: 将代码段反汇编的同时&#xff0c;将反汇编代码与源代码交替显示&#xff0c;编译时需要使用-g参数&#xff0c;即需要调试信…

Hadoop技术与应用的习题

第一章测验 1、下面哪个选项不属于Google的三驾马车&#xff1f; A.HDFS B.MapReduce C.BigTable D.GFS 2、下面哪个思想是为了解决PageRank&#xff08;网页排名&#xff09;的问题&#xff1f; A.GFS B.BigTable C.MapReduce D.YARN 3、GFS 存储的文件都被分割成固定大小的…

CAN基础知识

CAN 简介 CAN 是 Controller Area Network 的缩写&#xff08;以下称为 CAN&#xff09;&#xff0c;是 ISO 国际标准化的串行通信 协议。在当前的汽车产业中&#xff0c;出于对安全性、舒适性、方便性、低公害、低成本的要求&#xff0c;各种 各样的电子控制系统被开发了出来…

简单的用Python采集股票数据,保存表格后分析历史数据

前言 字节跳动如果上市&#xff0c;那么钟老板将成为我国第一个世界首富 趁着现在还没上市&#xff0c;咱们提前学习一下用Python分析股票历史数据&#xff0c;抱住粗大腿坐等起飞~ 好了话不多说&#xff0c;我们直接开始正文 准备工作 环境使用 Python 3.10 解释器Pychar…

如何应用ChatGPT撰写、修改论文及工作报告,提供写作能力及优化工作??

如果我想让gpt从pdf文档中提取相关关键词的内容&#xff0c;可以怎么做呢&#xff1f;&#xff1f;我们评论区讨论 ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&am…

爱上C语言:scanf、gets以及getchar输入字符串你真的懂了吗

&#x1f680; 作者&#xff1a;阿辉不一般 &#x1f680; 你说呢&#xff1a;不服输的你&#xff0c;他们拿什么赢 &#x1f680; 专栏&#xff1a;爱上C语言 &#x1f680;作图工具&#xff1a;draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话&#xff0c;还请点赞…