AcWing479.加分二叉树(区间DP)题解
加分二叉树
题目传送门
题目描述
设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号。
每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:
subtree的左子树的加分 × subtree的右子树的加分 + subtree的根的分数
若某个子树为空,规定其加分为1。叶子的加分就是叶节点本身的分数,不考虑它的空子树。
试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。
要求输出:
(1)tree的最高加分
(2)tree的前序遍历
输入格式
第1行:一个整数n,为节点个数。
第2行:n个用空格隔开的整数,为每个节点的分数(0<分数<100)。
输出格式
第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。
第2行:n个用空格隔开的整数,为该树的前序遍历。如果存在多种方案,则输出字典序最小的方案。
数据范围
n<30
输入样例:
5
5 7 1 2 10
输出样例:
145
3 1 2 4 5
题解:
区间DP同样适用于二叉树:
枚举二叉树的节点个数 len, 枚举二叉树的组成区间(l, r), 枚举根节点 k, 从而得到状态转移方程式:
f[ l ] [ r ] = max(f[ l ] [ r ], f[ l ] [ k - 1] + f[ l ] [k + 1], + w[k])
更新最大值的同时, 记录每一个树的根节点
//DP[i][j] 表示区间[i ~ j] 表示为一个二叉树时的分数的最大值
#include<iostream>
using namespace std;
const int N = 35;
int n;
int w[N];
int f[N][N], g[N][N]; // g数组用来存储每一个区间的根节点
void dfs(int l, int r, int k)
{if(l > r)return ;cout << k << ' ';dfs(l, k - 1, g[l][k - 1]);dfs(k + 1, r, g[k + 1][r]);
}
int main()
{cin >> n;for(int i = 1; i <= n; i++)cin >> w[i];for(int len = 1; len <= n; len++){ //枚举区间长度for(int l = 1; l + len - 1 <= n; l++){ //枚举起点int r = l + len - 1; //得到右端点if(len == 1){ //如果是根节点f[l][r] = w[l]; g[l][r] = l;}else{for(int k = l; k <= r; k++){ //枚举根节点//判断左子树是否为空int left = k == l ? 1 : f[l][k - 1]; //得到左子树和右子树的分数int right = k == r ? 1 : f[k + 1][r];if(left * right + w[k] > f[l][r]){ //更新最大值f[l][r] = left * right + w[k];g[l][r] = k; //跟新根节点}}}}}cout << f[1][n] << endl;dfs(1, n, g[1][n]);return 0;
}
AcWing479.加分二叉树(区间DP)题解相关推荐
- AcWing1069.凸多边形的划分(区间DP)题解
凸多边形的划分 题目传送门 题目描述 给定一个具有 N 个顶点的凸多边形,将顶点从 1 至 N 标号,每个顶点的权值都是一个正整数. 将这个凸多边形划分成 N−2 个互不相交的三角形,对于每个三角形, ...
- AcWing.282石子合并(区间DP)题解
石子合并 题目描述 设有N堆石子排成一排,其编号为1,2,3,-,N. 每堆石子有一定的质量,可以用一个整数来描述,现在要将这N堆石子合并成为一堆. 每次只能合并相邻的两堆,合并的代价为这两堆石子的质 ...
- P1040 加分二叉树【dp+深搜】
题目描述 设一个nn个节点的二叉树tree的中序遍历为(1,2,3,-,n1,2,3,-,n),其中数字1,2,3,-,n1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第ii个节 ...
- AcWing321.棋盘分割(区间DP)题解
棋盘分割 题目传送门 题目描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘 ...
- 区间dp入门——总结+习题+解析
前天学长拉了个区间dp的专题,花了两个做,今天就来做个总结吧!!! 区间dp其实就是一种建立在线性结构上的对区间的动态规划,dp本来就是很奇妙的东西,也没有什么套路,就是一种思考的数学思维方式,只有做 ...
- 【树形区间DP】加分二叉树(ssl 1033/luogu 1040)
加分二叉树 ssl 1033 luogu 1040 题目大意: 有一棵中序遍历为1,2,3-n的二叉树(当然二叉树的样子没有固定),现在给出每个节点的分数,一个节点的加数=两个子节点的加数相乘+当前节 ...
- DP专练1( [NOIP 2003]加分二叉树 + 太空梯 )
我们先慢慢来 加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 代码实现 太空梯 题目 题解 代码实现 加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 其实说白了,这个*序就是根ro ...
- 【树型DP】加分二叉树
问题 b: [树型DP]加分二叉树 时间限制: 1 Sec 内存限制: 64 MB 提交: 8 解决: 6 [提交] [状态] [讨论版] [命题人:admin] 题目描述 科技忽略了过程就是魔法 ...
- CSP认证201612-4 压缩编码[C++题解]:区间dp、huffman树、石子合并
题目分析 来源:acwing 分析: 本题难在想到是区间dp.想到区间dp之后,这就是石子合并的代码直接默写. 那么是如何建模的呢?我们把huffman编码(这里要求按照字典序大小编码,和huffma ...
最新文章
- 麻省理工人工智能实验室发现更小更容易训练的神经网络
- 计算机数控装置论文,数控专业(论文)范文.doc
- Winform将网页生成图片
- java基础之访问控制符
- PDF数据防扩散系统方案
- centos 初学者_初学者:如何在Outlook 2013中创建和管理任务
- 一张图看懂阿里云网络产品[二] 专有网络VPC
- vsftpd 启动 vsftpd:500 OOPS: bad bool value in config file for: guest_enable
- java工具类与集合类_JAVA学习---集合和工具类
- oracle 除法问题,javascript中除法问题
- 从数组中删除最后一项
- 在前台或会员中心获取表单向导里提交的数据
- iOS xcode The certificate used to sign Administrator has either expired or has been revoked. An u
- 软件工程中的十三种文档
- 从混沌熬到风口:移动FM的五年之争
- Hadoop单机版安装
- 深入理解HTTP/HTTPS协议
- 百乐达斯城全新梦幻主题乐园幻乐堡在韩国开业
- 使用POI为Excel添加数据有效性验证
- PCI-Express转4串/8串/28串口CH384的硬件配置及设计