P1040 [NOIP 2003 提高組] 加分二叉樹 題解

題目描述
設一個 n n n 個節點的二叉樹 tree \text{tree} tree 的中序遍歷為 ( 1 , 2 , 3 , … , n ) (1,2,3,\ldots,n) (1,2,3,,n),每個節點都有一個分數(均為正整數)。任一棵子樹 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。要求輸出:

tree \text{tree} tree 的最高加分

tree \text{tree} tree 的前序遍歷

輸入格式

1 1 1 行:整數 n n n(節點數)

2 2 2 行: n n n 個空格分隔的整數(節點分數)

輸出格式

1 1 1 行:最高加分

2 2 2 行:二叉樹的前序遍歷序列(空格分隔)

數據范圍
1 ≤ n < 30 1 \leq n < 30 1n<30,節點分數是小于 100 100 100 的正整數,答案不超過 4 × 10 9 4 \times 10^9 4×109

解題思路
算法分析:區間動態規劃
本題需要構造一棵中序遍歷為 1 ~ n 1 \sim n 1n 的二叉樹,使得其加分最大。由于中序遍歷的特性(左子樹-根-右子樹),我們可以使用區間動態規劃來解決:

狀態定義:

dp[l][r]:表示節點編號在區間 [ l , r ] [l, r] [l,r] 內構成的子樹的最大加分

root[l][r]:表示區間 [ l , r ] [l, r] [l,r] 構成最大加分子樹的根節點編號

狀態轉移:

枚舉區間 [ l , r ] [l, r] [l,r] 中的每個節點 k k k 作為根節點

計算以 k k k 為根時的加分:

k = l k = l k=l(無左子樹):加分 = 右子樹加分 + 根節點分數

k = r k = r k=r(無右子樹):加分 = 左子樹加分 + 根節點分數

否則:加分 = 左子樹加分 × 右子樹加分 + 根節點分數

更新區間 [ l , r ] [l, r] [l,r] 的最大加分和對應的根節點

前序遍歷輸出:

使用遞歸方法輸出:根節點 → 左子樹 → 右子樹

根據記錄的 root 數組確定每個子樹的根節點

復雜度分析
時間復雜度: O ( n 3 ) O(n^3) O(n3)
三重循環:枚舉區間長度( n n n)、區間起點( n n n)、根節點位置( n n n)

空間復雜度: O ( n 2 ) O(n^2) O(n2)
存儲二維DP數組和根節點記錄數組

代碼實現

#include<bits/stdc++.h>
using namespace std;
const int N=35;
int n,dp[N][N],tree[N][N];
int qiu(int l,int k,int r)
{if(k==l)return dp[k+1][r]+dp[k][k];if(r==k)return dp[l][k-1]+dp[k][k];return dp[l][k-1]*dp[k+1][r]+dp[k][k];
}
void shuchu(int l,int r)
{if(r<l)return;cout<<tree[l][r]<<" ";shuchu(l,tree[l][r]-1);shuchu(tree[l][r]+1,r);
}
int main()
{ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);cin>>n;for(int i=1;i<=n;i++){cin>>dp[i][i];tree[i][i]=i;}for(int i=2;i<=n;i++)for(int j=1;j<=n-i+1;j++){int jj=j+i-1;for(int r=j;r<=jj;r++)if(qiu(j,r,jj)>dp[j][jj]){tree[j][jj]=r;dp[j][jj]=qiu(j,r,jj);}}cout<<dp[1][n]<<'\n';shuchu(1,n);
//	cout<<tree[1][2];return 0;
}

外層循環:枚舉區間長度(從2到n)

中層循環:枚舉區間起點(保證區間在[1,n]內)

內層循環:枚舉可能的根節點位置

計算當前根節點的加分并更新最大值和根節點記錄

  1. 前序遍歷輸出
void shuchu(int l, int r) {if (l > r) return;cout << tree[l][r] << " ";shuchu(l, tree[l][r] - 1);shuchu(tree[l][r] + 1, r);
}

遞歸輸出前序遍歷序列

輸出順序:當前根節點 → 左子樹區間 → 右子樹區間

遞歸終止條件:區間為空(l > r)

  1. 邊界處理函數
int qiu(int l, int k, int r) {if (k == l) // 左子樹為空return dp[k][k] + dp[k+1][r];if (k == r) // 右子樹為空return dp[k][k] + dp[l][k-1];return dp[k][k] + dp[l][k-1] * dp[k+1][r];
}

處理根節點在區間端點的特殊情況

當根節點在左端點時,左子樹為空(加分為1)

當根節點在右端點時,右子樹為空(加分為1)

示例分析
輸入:

5
5 7 1 2 10

輸出:

145
3 1 2 4 5

解釋:
最高加分145對應的二叉樹結構:

    3/ \1   4\   \2   5
前序遍歷:3 → 1 → 2 → 4 → 5

加分計算:

葉子節點加分:節點2(2分)、節點5(10分)

子樹[1,2]:左空(1) × 右節點2(2) + 根節點1(7) = 1×2+7=9

子樹[4,5]:左節點4(1) × 右節點5(10) + 根節點4(1) = 1×10+1=11

整棵樹:左子樹1,2 × 右子樹4,5 + 根節點3(5) = 9×11+5=104

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84273.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84273.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84273.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Golang面試題】Data Race 問題怎么檢測?

Go Race Detector 深度指南&#xff1a;原理、用法與實戰技巧 一、什么是數據競爭&#xff1f; 在并發編程中&#xff0c;數據競爭發生在兩個或多個 goroutine 同時訪問同一內存位置&#xff0c;且至少有一個是寫操作時。這種競爭會導致不可預測的行為和極其難以調試的問題。…

257. 二叉樹的所有路徑(js)

257. 二叉樹的所有路徑——DFS 回溯&#xff08;js&#xff09; 題目描述解題思路完整代碼時間復雜度分析 題目描述 257. 二叉樹的所有路徑 解題思路 題意理解 給定一棵二叉樹&#xff0c;要求返回所有從根節點到葉子節點的路徑&#xff0c;路徑以字符串形式表示&#xff0c…

自動化文檔生成工具(親測可運行)

本文介紹了一個用Java編寫的自動化文檔生成工具&#xff0c;通過讀取開發清單文本自動生成格式規范的Word文檔。該工具的主要特點包括&#xff1a; 采用Apache POI庫處理Word文檔&#xff0c;支持多級標題和段落自動生成實現中文數字轉換功能&#xff0c;將編號轉換為"一、…

湖北理元理律師事務所債務優化模型:法律與生活的平衡之道

在債務重組領域&#xff0c;專業機構需同時解決兩個矛盾&#xff1a;法律合規性與債務人可持續生存能力。湖北理元理律師事務所通過“三維干預模型”&#xff0c;在武漢某餐飲連鎖企業債務危機中驗證了該方案的有效性。 一、法律底層設計&#xff1a;還款方案的合法性審查 以該…

Web3-代幣ERC20/ERC721以及合約安全溢出和下溢的研究

Web3-代幣ERC20/ERC721以及合約安全溢出和下溢的研究 以太坊上的代幣 如果你對以太坊的世界有一些了解&#xff0c;你很可能聽人們聊過代幣— ERC20代幣 一個 代幣 在以太坊基本上就是一個遵循一些共同規則的智能合約——即它實現了所有其他代幣合約共享的一組標準函數&…

論文筆記 <交通燈><多智能體>MetaLight:基于價值的元強化學習用于交通信號控制

今天看的論文是這篇MetaLight:基于價值的元強化學習用于交通信號控制 里面提到的創新點就是MetaLight框架&#xff1a;他目標是讓交通信號控制智能體&#xff08;Agent&#xff09;在新路口&#xff08;即使結構或流量模式不同&#xff09;上能??快速學習??&#xff08;Few…

華為OD-2024年E卷-尋找符合要求的最長子串[200分] -- python

問題描述&#xff1a; 給定一個字符串s&#xff0c;找出這樣一個子串: 1)該子串中的任意一個字符最多出現2次; 2)該子串不包含指定某個字符; 請你找出滿足該條件的最長子串的長度。 輸入描述 第一行為要求不包含的指定字符&#xff0c;為單個字符&#xff0c;取值范圍[0-9a-zA…

CppCon 2016 學習:What C++ Programmers Need to Know about Header <random>

隨機數生成的歷史背景 Middle-Square 方法&#xff08;中位平方法&#xff09;&#xff1a; 已知最早的隨機算法之一或由修道士 Brother Edvin 在 1245 年發明由 John von Neumann 在 1949 年重新發現缺點明顯&#xff0c;但執行速度快 Monte Carlo 方法&#xff1a; 起初是…

Origin:誤差棒點線圖繪制

1.首先將你的數據復制到表格 2.選中B(y)列數據&#xff0c;依次點擊圖示選項 3.選中圖中紅框數據&#xff0c;點擊繪制點線圖即可 4.結果展示

Spring 源碼學習 1:ApplicationContext

Spring 源碼學習 1&#xff1a;ApplicationContext Bean 定義和 Bean 實例 AnnotationConfigApplicationContext 首先&#xff0c;創建一個最簡單的 Spring Boot 應用。 在入口類中接收SpringApplication.run的返回值&#xff1a; SpringBootApplication public class Dem…

CppCon 2017 學習:Design Patterns for Low-Level Real-Time Rendering

這段內容講的是離散顯卡&#xff08;Discrete GPU&#xff09;中的內存管理模型&#xff0c;重點是CPU和GPU各自獨立管理自己的物理內存&#xff0c;以及它們如何通過虛擬內存和DMA引擎實現高效通信。以下是詳細的理解和梳理&#xff1a; 1. 基本概念 CPU 和 GPU 是兩個獨立的…

【單調隊列】-----【原理+模版】

單調隊列 一、什么是單調隊列&#xff1f; 單調隊列是一種在滑動窗口或區間查詢中維護候選元素單調性的數據結構&#xff0c;通常用于解決“滑動窗口最大值/最小值”等問題。 核心思想是&#xff1a;利用雙端隊列&#xff08;deque&#xff09;維護當前窗口內或候選范圍內元素…

CSS語法中的選擇器與屬性詳解

CSS:層疊樣式表&#xff0c;Cascading Style Sheets 層疊樣式表 內容和樣式分離解耦&#xff0c;便于修改樣式。 特殊說明&#xff1a; 最后一條聲明可以沒有分號&#xff0c;但是為了以后修改方便&#xff0c;一般也加上分號為了使用樣式更加容易閱讀&#xff0c;可以將每條代…

模擬設計的軟件工程項目

考核題目 論文論述題&#xff1a;結合你 參與開發、調研或模擬設計的軟件工程項目 &#xff0c;撰寫一篇論文 完成以下任務&#xff0c;論文題目為《面向微服務架構的軟件系統設計與建模分析》&#xff0c;總分&#xff1a; 100 分。 1. 考核內容&#xff1a; 一、系統論述…

個人理解redis中IO多路復用整個網絡處理流

文章目錄 1.redis網絡處理流2.理解通知機制 1.redis網絡處理流 10個客戶端通過TCP與Redis建立socket連接&#xff0c;發送GET name指令到服務器端。服務器端的網卡接收數據&#xff0c;數據進入內核態的網絡協議棧。Redis通過IO多路復用機制中的epoll向內核注冊監聽這些socket的…

【鄭州輕工業大學|數據庫】數據庫課設-酒店管理系統

該數據課設是一個基于酒店管理系統的數據庫設計 建庫語句 create database hotel_room default charset utf8 collate utf8_general_ci;建表語句 use hotel_room;-- 房型表 create table room_type( id bigint primary key auto_increment comment 房型id, name varchar(50)…

TCP 三次握手與四次揮手詳解

前言 在當今互聯網時代&#xff0c;前端開發的工作范疇早已超越了簡單的頁面布局和交互設計。隨著前端應用復雜度的不斷提高&#xff0c;對網絡性能的優化已成為前端工程師不可忽視的重要職責。而要真正理解并優化網絡性能&#xff0c;就需要探究支撐整個互聯網的基礎協議——…

RTD2735TD/RTD2738 (HDMI,DP轉EDP 高分辨率高刷新率顯示器驅動芯片)

一、芯片概述 RTD2738是瑞昱半導體&#xff08;Realtek&#xff09;推出的一款高性能顯示驅動芯片&#xff0c;專為高端顯示器、便攜屏、專業顯示設備及多屏拼接系統設計。其核心優勢在于支持4K分辨率下240Hz高刷新率及8K30Hz顯示&#xff0c;通過集成DisplayPort 1.4a與HDMI …

C++實現手寫strlen函數

要實現求字符串長度的函數&#xff0c;核心思路是通過指針或索引遍歷字符串&#xff0c;直到遇到字符串結束標志 \0 。以下是兩種常見的實現方式&#xff1a; 指針遍歷版本 #include <iostream> using namespace std; // 指針方式實現strlen size_t myStrlen(const cha…

NVPL 函數庫介紹和使用

文章目錄 NVPL 函數庫介紹和使用什么是 NVPLNVPL 的主要組件NVPL 的優勢安裝 NVPL基本使用示例示例1&#xff1a;使用 NVPL RAND 生成隨機數示例2&#xff1a;使用 NVPL FFT 進行快速傅里葉變換 編譯 NVPL 程序性能優化建議總結 NVPL 函數庫介紹和使用 什么是 NVPL NVPL (NVI…