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

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

题目描述

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

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

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

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

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

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

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

解法

因为中序遍历保证是 \(1 \to n\),所以可以从这里入手。中序遍历中,如果一个数是这颗子树的根,那么中序遍历的序列以这个数为分割点的左边是左子树,右边是右子树。

我们考虑区间 \(dp\),设计状态 \(dp_{i,j}\) 表示中序遍历中 \(i \to j\) 区间的组成的子树所可能得到分数的最大值。

则有状态转移方程:

\[dp_{i,j} = \max^{j}_{k = i}\{dp_{i,k - 1} \times dp_{k + 1,j} + dp_{k,k}\} \]

那么第一问就做完了。

我们可以在转移的时候加一个判断,用 \(rt_{i,j}\) 表示 \(i \to j\) 中取得最大值是这个区间的根的编号。

用代码表示就是:

if(dp[i][j] < dp[i][k - 1] * dp[k + 1][j] + dp[k][k]){
	dp[i][j] = dp[i][k - 1] * dp[k + 1][j] + dp[k][k];
	rt[i][j] = k;
}

题目要求输出前序遍历,则递归输出即可。

code:

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int MAXN = 35;
int n;
int val[MAXN];
int dp[MAXN][MAXN];
int rt[MAXN][MAXN];
void print(int l,int r){
	if(l > r) return;
	cout << rt[l][r] << " ";
	print(l,rt[l][r] - 1);
	print(rt[l][r] + 1,r);
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	for(int i = 0;i <= MAXN - 1;i++){
		for(int j = 0;j <= MAXN - 1;j++){
			dp[i][j] = 1;
		}
	}
	for(int i = 1;i <= n;i++) cin >> val[i],dp[i][i] = val[i];
	for(int i = 1;i <= n;i++) rt[i][i] = i;+
	for(int len = 2;len <= n;len++){
		for(int i = 1;i <= n - len + 1;i++){
			int j = i + len - 1;
			for(int k = i;k <= j;k++){
				if(dp[i][j] < dp[i][k - 1] * dp[k + 1][j] + dp[k][k]){
					dp[i][j] = dp[i][k - 1] * dp[k + 1][j] + dp[k][k];
					rt[i][j] = k;
				}
			}
		}
	}
	cout << dp[1][n] << endl;
	print(1,n);
	return 0;
}
posted @ 2024-10-23 15:56  wyl123ly  阅读(63)  评论(0)    收藏  举报