【NOIP提高组】加分二叉树

news2025/1/17 6:08:32

【NOIP提高组】加分二叉树


💐The Begin💐点点关注,收藏不迷路💐

在这里插入图片描述

设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:
subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数
若某个子树为主,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空
子树。
试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出;
(1)tree的最高加分
(2)tree的前序遍历

输入

第1行:一个整数n(n<30),为节点个数。
第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。

输出

第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。
第2行:n个用空格隔开的整数,为该树的前序遍历。

样例输入

5
5 7 1 2 10

样例输出

145
3 1 2 4 5  

以下是用 C 语言实现的代码:

#include <stdio.h>

#define MAX_NODE 60

// 定义最大节点数
int score[MAX_NODE][MAX_NODE]; // score 存储子树的最大加分
int midNode[MAX_NODE][MAX_NODE]; // midNode 存储子树最大加分时的根节点位置
int nodeVal[MAX_NODE]; // nodeVal 存储节点的分数
int numNodes; // numNodes 代表节点总数

// 递归计算最大加分函数
int findMaxScore(int start, int end) {
    // 如果区间无效,返回 1
    if (start > end)
        return 1;
    // 如果已经计算过该区间的最大加分,直接返回结果
    if (score[start][end])
        return score[start][end];
    // 如果区间只有一个节点,最大加分就是该节点的分数
    if (start == end) {
        score[start][end] = nodeVal[start];
    } else {
        int tempScore;
        for (int i = start; i <= end; ++i) {
            // 递归计算左右子树的最大加分并加上当前节点的分数
            tempScore = findMaxScore(start, i - 1) * findMaxScore(i + 1, end) + nodeVal[i];
            // 更新最大加分和对应的中间节点
            if (tempScore > score[start][end]) {
                score[start][end] = tempScore;
                midNode[start][end] = i;
            }
        }
    }
    return score[start][end];
}

// 输出前序遍历函数
void printPreorder(int start, int end) {
    // 如果区间无效,直接返回
    if (start > end)
        return;
    // 如果区间只有一个节点,直接输出该节点
    if (start == end) {
        printf("%d ", start);
    } else {
        // 输出中间节点
        printf("%d ", midNode[start][end]);
        // 递归输出左子树和右子树
        printPreorder(start, midNode[start][end] - 1);
        printPreorder(midNode[start][end] + 1, end);
    }
}

int main() {
    scanf("%d", &numNodes);
    for (int i = 1; i <= numNodes; ++i) {
        scanf("%d", &nodeVal[i]);
    }
    printf("%d\n", findMaxScore(1, numNodes));
    printPreorder(1, numNodes);
    return 0;
}

以下是用 C++实现的代码:

#include <iostream>

const int MAX_N = 60;

// 定义最大节点数
int score[MAX_N][MAX_N]; // score 存储子树的最大加分
int midNode[MAX_N][MAX_N]; // midNode 存储子树最大加分时的根节点位置
int nodeVal[MAX_N]; // nodeVal 存储节点的分数
int numNodes; // numNodes 代表节点总数

// 递归计算最大加分函数
int findMaxScore(int start, int end) {
    // 如果区间无效,返回 1
    if (start > end)
        return 1;
    // 如果已经计算过该区间的最大加分,直接返回结果
    if (score[start][end])
        return score[start][end];
    // 如果区间只有一个节点,最大加分就是该节点的分数
    if (start == end) {
        score[start][end] = nodeVal[start];
    } else {
        int tempScore;
        for (int i = start; i <= end; ++i) {
            // 递归计算左右子树的最大加分并加上当前节点的分数
            tempScore = findMaxScore(start, i - 1) * findMaxScore(i + 1, end) + nodeVal[i];
            // 更新最大加分和对应的中间节点
            if (tempScore > score[start][end]) {
                score[start][end] = tempScore;
                midNode[start][end] = i;
            }
        }
    }
    return score[start][end];
}

// 输出前序遍历函数
void printPreorder(int start, int end) {
    // 如果区间无效,直接返回
    if (start > end)
        return;
    // 如果区间只有一个节点,直接输出该节点
    if (start == end) {
        std::cout << start << " ";
    } else {
        // 输出中间节点
        std::cout << midNode[start][end] << " ";
        // 递归输出左子树和右子树
        printPreorder(start, midNode[start][end] - 1);
        printPreorder(midNode[start][end] + 1, end);
    }
}

int main() {
    std::cin >> numNodes;
    for (int i = 1; i <= numNodes; ++i) {
        std::cin >> nodeVal[i];
    }
    std::cout << findMaxScore(1, numNodes) << std::endl;
    printPreorder(1, numNodes);
    return 0;
}

以下是用 Java 实现的代码:

import java.util.Scanner;

class BinaryTreeScoreCalculator {
    // 定义最大节点数
    private static final int MAX_N = 60;

    // 存储子树的最大加分
    static int[][] score = new int[MAX_N][MAX_N];
    // 存储子树最大加分时的根节点位置
    static int[][] midNode = new int[MAX_N][MAX_N];
    // 存储节点的分数
    static int[] nodeVal = new int[MAX_N];
    // 代表节点总数
    static int numNodes;

    // 递归计算最大加分函数
    static int findMaxScore(int start, int end) {
        // 如果区间无效,返回 1
        if (start > end)
            return 1;
        // 如果已经计算过该区间的最大加分,直接返回结果
        if (score[start][end]!= 0)
            return score[start][end];
        // 如果区间只有一个节点,最大加分就是该节点的分数
        if (start == end) {
            score[start][end] = nodeVal[start];
        } else {
            int tempScore;
            for (int i = start; i <= end; ++i) {
                // 递归计算左右子树的最大加分并加上当前节点的分数
                tempScore = findMaxScore(start, i - 1) * findMaxScore(i + 1, end) + nodeVal[i];
                // 更新最大加分和对应的中间节点
                if (tempScore > score[start][end]) {
                    score[start][end] = tempScore;
                    midNode[start][end] = i;
                }
            }
        }
        return score[start][end];
    }

    // 输出前序遍历函数
    static void printPreorder(int start, int end) {
        // 如果区间无效,直接返回
        if (start > end)
            return;
        // 如果区间只有一个节点,直接输出该节点
        if (start == end) {
            System.out.print(start + " ");
        } else {
            // 输出中间节点
            System.out.print(midNode[start][end] + " ");
            // 递归输出左子树和右子树
            printPreorder(start, midNode[start][end] - 1);
            printPreorder(midNode[start][end] + 1, end);
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        numNodes = scanner.nextInt();
        for (int i = 1; i <= numNodes; ++i) {
            nodeVal[i] = scanner.nextInt();
        }
        System.out.println(findMaxScore(1, numNodes));
        printPreorder(1, numNodes);
    }
}

在这里插入图片描述


💐The End💐点点关注,收藏不迷路💐

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

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

相关文章

【Java并发编程】信号量Semaphore详解

一、简介 Semaphore&#xff08;信号量&#xff09;&#xff1a;是用来控制同时访问特定资源的线程数量&#xff0c;它通过协调各个线程&#xff0c;以保证合理的使用公共资源。 Semaphore 一般用于流量的控制&#xff0c;特别是公共资源有限的应用场景。例如数据库的连接&am…

redis详细教程(2.List教程)

List是一种可以存储多个有序字符串的数据类型&#xff0c;其中的元素按照顺序排列&#xff08;可以重复出现&#xff09;&#xff0c;可以通过数字索引来访问列表中的元素&#xff0c;索引可以从左到右或者从右到左。 Redis 列表可以通过两种方式实现&#xff1a;压缩列表&…

力扣283-- 移动零

开始做梦的地方 力扣283 &#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 何解&#xff1f; 1&#xff0c;暴力枚举&#xff1a…

ElasticSearch备考 -- index rollover

一、题目 给索引my-index-000001&#xff0c;创建别名my-index&#xff0c;并设置rollover&#xff0c;满足以下三个条件的 The index was created 7 or more days ago.The index contains 5 or more documents.The index’s largest primary shard is 1GB or larger. 二、思考…

cmake命令使用

有关cmake的入门简介可参见 CMake入门教程_cmake静态test.c编译-CSDN博客 本文是进一步对cmake常用命令做进一步详述 配置项目 cmake_minimum_required 作用 配置cmake最低版本 用法 cmake_minimum_required(VERSION 3.0) project 作用&#xff1a;设置预设变量 PROJEC…

w002基于Springboot医护人员排班系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

Python数据分析基础

本文介绍了Python在数据分析中的应用&#xff0c;包括数据读取、清洗、处理和分析的基本操作。通过使用Pandas和Numpy库&#xff0c;我们可以高效地处理大量数据&#xff0c;并利用Matplotlib和Seaborn库进行数据可视化。 1. 引言 Python因其简洁的语法和强大的库支持&#x…

重学SpringBoot3-Spring WebFlux之Reactor事件感知 API

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ Spring WebFlux之Reactor事件感知 API 1. 什么是 doOnXxx 系列 API&#xff1f;2. doOnXxx API 的常用方法2.1 doOnNext()示例&#xff1a;输出&#xff1a; 2.2 doOnErr…

OCR经典神经网络(三)LayoutLM v2算法原理及其在发票数据集上的应用(NER及RE)

OCR经典神经网络(三)LayoutLM v2算法原理及其在发票数据集上的应用(NER及RE) LayoutLM系列模型是微软发布的、文档理解多模态基础模型领域最重要和有代表性的工作&#xff1a; LayoutLM v2&#xff1a;在一个单一的多模态框架中对文本&#xff08;text&#xff09;、布局&…

OpenAI GPT-o1实现方案记录与梳理

本篇文章用于记录从各处收集到的o1复现方案的推测以及介绍 目录 Journey Learning - 上海交通大学NYUMBZUAIGAIRCore IdeaKey QuestionsKey TechnologiesTrainingInference A Tutorial on LLM Reasoning: Relevant methods behind ChatGPT o1 - UCL汪军教授Core Idea先导自回归…

anaconda 创建环境失败 解决指南

anaconda 创建环境失败 解决指南 一、问题描述 我在宿舍有一台电脑。由于我经常泡在实验室&#xff0c;所以那台电脑不是经常用&#xff0c;基本吃灰。昨天晚上突然有在那台电脑上使用Camel-AI部署多智能体协同需求&#xff0c;便戳开了电脑&#xff0c;问题也随之而来。 当…

开源实时数仓的构建

设计计思路 基本思路 开源数据平台的设计思路是通过 Flink SQL Batch、StartRocks SQL 、StartRocks物化视图 的能力实现一个离线任务的开发&#xff1b;使用 DolphinScheduler 进行离线工作流编排和调度&#xff1b;通过 Flink CDC 和 Flink SQL 实现流处理能力&#xff0c;进…

【自然语言处理】BERT模型

BERT&#xff1a;Bidirectional Encoder Representations from Transformers BERT 是 Google 于 2018 年提出的 自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;它基于 Transformer 架构的 Encoder 部分。BERT 的出现极大提升了 NLP 任务的性能&#xff0c;如问答系…

Linux基础知识 - C(自学使用)

1.C语言基础知识 参考博客&#xff1a; https://blog.csdn.net/qq_45254369/article/details/126023482?ops_request_misc%257B%2522request%255Fid%2522%253A%252277629891-A0F3-4EFC-B1AC-410093596085%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%…

【Canvas与图标】六色彩虹圆角六边形图标

【成图】 120*120的png图标 以下是各种大小图&#xff1a; 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>六色彩虹圆角六边形…

Android简单控件实现简易计算器

学了一些Android的简单控件&#xff0c;用这些布局和控件&#xff0c;设计并实现一个简单计算器。 计算器的界面分为两大部分&#xff0c;第一部分是上方的计算表达式&#xff0c;既包括用户的按键输入&#xff0c;也包括计算结果 数字&#xff1b;第二部分是下方的各个按键&a…

1U服务器和Hyper-V虚拟机使用记录

记录最近接触服务器和虚拟机的一些使用操作知识 背景&#xff1a;1U服务器上架使用&#xff0c;备份其他服务器vm虚拟机&#xff0c;Hyper-V管理虚拟机使用测试 设备&#xff1a;IBM3550服务器交换机&#xff0c; 移动硬盘&#xff1a;附加存储盘&#xff0c; u盘1&#xff1…

在虚拟化环境中,虚拟机的资源分配是否真的能够完全等效于物理服务器?是否有某些特定的工作负载在虚拟化环境中始终无法达到理想表现?

目录 1. 虚拟化技术的基本原理与资源管理 2. 资源分配的等效性问题 3. 特定工作负载在虚拟化环境中的表现 4. 性能优化与虚拟化环境的选择 5. 结论 虚拟化技术的广泛应用为数据中心的资源管理与部署带来了革命性的变化。虚拟机&#xff08;VM&#xff09;通过抽象化的方式…

【了解一下静态代理与动态代理】

文章目录 一.什么是静态代理与动态代理二.静态代理三.动态代理1.jdk动态代理2.cglib动态代理 四.小结 一.什么是静态代理与动态代理 什么是代理&#xff1f;代理是一种设计模式&#xff0c;在这种模式中&#xff0c;一个类&#xff08;代理类&#xff09;代表另一个类&#xff…

【ArcGIS Pro实操第8期】绘制WRF三层嵌套区域

【ArcGIS Pro实操第8期】绘制WRF三层嵌套区域 数据准备ArcGIS Pro绘制WRF三层嵌套区域Map-绘制三层嵌套区域更改ArcMap地图的默认显示方向指定数据框范围 Map绘制研究区Layout-布局出图 参考 本博客基于ArcGIS Pro绘制WRF三层嵌套区域&#xff0c;具体实现图形参考下图&#xf…