加分二叉树

原题链接:https://www.luogu.org/problem/show?pid=1040

刚拿到这道题的我是懵逼的,因为刚开始除了暴力我完全想不到从哪入手。

其实这题是一个区间dp和dfs,代码还是挺简单的。

参考了一篇题解,对那位大佬表示由衷的敬意。

设f[i][j]表示在区间(i,j)内的最大加分,那么有f[i][j] = max(f[i][k-1]*f[k+1][j]+a[k]) ,a[k]代表第i个点的分数,k是枚举的根节点,即状态转移方程的那个式子是指的在区间(i,j)上的以k为根节点的最大分数。

还记得区间dp的基本思路吗?由小区间推出大区间,这题也是这样,i从n倒推至1,j从i正推至n,而中间的枚举根节点k的范围是[i,j]。

同时我们还需要一个数组n[i][j]表示在区间(i,j)加分最大时的根节点,在后面会用到。

最高加分便是f[1][N]。//为了不和n数组重复用一个大写

考虑下一个问题,如何输出一棵树的前序遍历?

还记得什么是前序遍历吗?先根,再左子树,再右子树。

要输出一个遍历,递归输出就好。首先输出当前的点(根节点),然后输出左子树,再输出右子树,简单的划分。

参考代码:

 1 #include <iostream>
 2 #define maxn 35
 3 using namespace std;
 4 int a[maxn];
 5 int N;
 6 int f[maxn][maxn];
 7 int n[maxn][maxn];
 8
 9
10 void dfs(int l,int r){
11     if (l>r)
12         return;
13     int mid = n[l][r];
14     cout << mid << " ";
15     dfs(l,mid-1);
16     dfs(mid+1,r);
17 }
18
19 int main(){
20     cin >> N;
21     for (int i=0;i<=N;i++)
22         for (int j=0;j<=N;j++)
23             f[i][j] = 1;
24
25     for (int i=1;i<=N;i++){
26         cin >> a[i];
27         f[i][i] = a[i];
28         n[i][i] = i;
29     }
30
31     for (int i=N-1;i>=1;i--)
32         for (int j=i+1;j<=N;j++)
33             for (int k=i;k<=j;k++)
34                 if (f[i][k-1]*f[k+1][j]+a[k]>f[i][j]){
35                     n[i][j]=k;
36                     f[i][j]=f[i][k-1]*f[k+1][j]+a[k];
37                 }
38     cout << f[1][N] << endl;
39     dfs(1,N);
40
41     return 0;
42 }
时间: 2024-10-11 13:19:06

加分二叉树的相关文章

NOIP2003 加分二叉树

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

1090 加分二叉树

1090 加分二叉树 2003年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下: subtree的左子树的加分× subtree

NOIP2003加分二叉树[树 区间DP]

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

【洛谷】P1040 加分二叉树

[洛谷]P1040 加分二叉树 题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下: subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数. 若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数.不考虑它的空子树. 试求一棵符合中

NOIP2003TG 加分二叉树 区间DP

加分二叉树 (binary) [问题描述] 设一个 n 个节点的二叉树 tree 的中序遍历为( l,2,3,…,n ),其中数字 1,2,3,…,n 为节点编号.每个节点都有一个分数(均为正整数),记第 j 个节点的分数为 di , tree 及它的每个子树都有一个加分,任一棵子树 subtree (也包含 tree 本身)的加分计算方法如下: subtree 的左子树的加分 × subtree 的右子树的加分+ subtree 的根的分数 若某个子树为空,规定其加分为 1 ,叶子的加分就是叶

P1040 加分二叉树

转自:(http://www.cnblogs.com/geek-007/p/7197439.html) 经典例题:加分二叉树(Luogu 1040) 设一个 n 个节点的二叉树 tree 的中序遍历为( 1,2,3,…,n),其中数字 1,2,3,…,n 为节点编号.每个节点都有一个分数(均为正整数),记第 i 个节点的分数为 di, tree 及它的每个子树都有一个加分,任一棵子树 subtree(也包含 tree 本身)的加分计算方法如下: subtree 的左子树的加分 × subtree

洛谷P1040 加分二叉树

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

cogs 106. [NOIP2003] 加分二叉树(区间DP)

106. [NOIP2003] 加分二叉树 ★☆   输入文件:jfecs.in   输出文件:jfecs.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 设 一个 n 个节点的二叉树 tree 的中序遍历为( l,2,3,…,n ),其中数字 1,2,3,…,n 为节点编号.每个节点都有一个分数(均为正整数),记第 j 个节点的分数为 di , tree 及它的每个子树都有一个加分,任一棵子树 subtree (也包含 tree 本身)的加分计算方法如下: su

Vijos 1100 加分二叉树

题目 1100 加分二叉树 2003年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下: subtree的左子树的加分× subtree的右子树的加分+subtree的根的

加分二叉树_解题报告_SSL1033_2003年分区联赛提高组之三_树形dp

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