1.简述:
描述设一个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的前序遍历
数据范围: ,每个节点的值满足
输入描述:第一行输入一个正整数 n ,表示二叉树节点的个数。
第二行输入 n 个正整数,表示二叉树中序遍历的节点分数
输出描述:输出最高加分和前序遍历结果。
示例1输入:
输出:
2.代码实现:
import java.util.*;
public class Main {
static int[][][] dp = new int[32][32][2];
static List<Integer> list = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] val = new int[n + 1];
for (int i = 1; i <= n; ++i)
val[i] = sc.nextInt();
for (int i = 0; i < n; ++i) {
for (int j = 1; j + i <= n; ++j) {
int r = j + i;
if (j == r) {
dp[j][r][0] = val[j];
dp[j][r][1] = j;
}else {
for (int k = j; k <= r; ++k) {
int left = k == j ? 1 : dp[j][k - 1][0];
int right = k == r ? 1 : dp[k + 1][r][0];
int sum = left * right + val[k];
if (sum > dp[j][r][0]) {
dp[j][r][0] = sum;
dp[j][r][1] = k;
}
}
}
}
}
getPre(dp[1][n][1], 1, n);
System.out.println(dp[1][n][0]);
for (int i: list)
System.out.print(i + " ");
}
private static void getPre(int cur, int l, int r) {
if (l > cur || r < cur) return;
list.add(cur);
getPre(dp[l][cur - 1][1], l, cur - 1);
getPre(dp[cur + 1][r][1], cur + 1, r);
}
}