P1040 加分二叉树(区间DP)
来源:互联网 发布:网站域名到期查询 编辑:程序博客网 时间:2024/05/19 17:56
P1040 加分二叉树 https://www.luogu.org/problemnew/show/1040
题目描述
设一个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(n<30),为节点个数。
第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。
输出格式:
第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。
第2行:n个用空格隔开的整数,为该树的前序遍历。
算法分析:
结合问题,如果整棵树的权值最大,必然有左子树的权值最大,右子树的权值也最大,符合最优性原理。
而却不是一道树规的题目。因为我们可以用区间动规的模型解决掉:直接定义一个f[i][j]表示从i到j的最大值,则
f[i][j]=max(f[i][k-1]*f[k+1][j]+f[k][k])
枚举k即可。
接下来是如何建树的问题,只有把树建好了,才能输出其前序遍历。于是,我们看到了两个关键词:二叉树,中序遍历。有了这两个关键词,加上区间动规,这棵树就能建起来了。根据二叉树的特性来建树。所以这颗树的前序遍历,只需要边动规边记录下root[i][j]=k表示i到j的根为k即可确定树的构造。
前序遍历(DLR)
前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
若二叉树为空则结束返回,否则:
(1)访问根结点
(2)前序遍历左子树
(3)前序遍历右子树
注意的是:遍历左右子树时仍然采用前序遍历方法。
如上图所示二叉树
前序遍历,也叫先根遍历,遍历的顺序是,根,左子树,右子树
遍历结果:ABCDEF
中序遍历,也叫中根遍历,顺序是 左子树,根,右子树
遍历结果:CBDAEF
后序遍历,也叫后根遍历,遍历顺序,左子树,右子树,根
遍历结果:CDBFEA
AC代码:
#include<iostream>#include<memory.h>using namespace std;int n;int f[35][35];int root[35][35];//root[a][b]表示a,b区间里父节点的编号。int get_Max(int left,int right){if(left>right){return 1;}if(f[left][right]==0){for(int i=left;i<=right;i++){int temp=f[left][right];f[left][right]=max((get_Max(left,i-1)*get_Max(i+1,right)+f[i][i]),f[left][right]);if(temp<f[left][right]){root[left][right]=i;//如果找到比当前更大的就更新,同时记录树根节点}}}return f[left][right];}void dfs(int left,int right){if((left>right)){return ;}else{cout<<root[left][right]<<' '; dfs(left,root[left][right]-1); dfs(root[left][right]+1,right);}}int main(){cin>>n;memset(f,0,sizeof(f));//数组初始化为0memset(root,0,sizeof(root));for(int i=1;i<=n;i++){int m;cin>>m;f[i][i]=m;root[i][i]=i;}cout<<get_Max(1,n)<<endl;dfs(1,n);return 0;}
- 区间dp-洛谷P1040 加分二叉树
- P1040 加分二叉树(区间DP)
- P1040 加分二叉树(树形dp)
- 洛谷P1040 加分二叉树(DP)
- 洛谷 P1040 加分二叉树
- 洛谷 P1040 加分二叉树
- 洛谷 P1040 加分二叉树
- 洛谷 P1040 加分二叉树
- 洛谷 [P1040]加分二叉树
- 加分二叉树 区间dp
- 洛谷 P1040 [NOIP2003 T3] 加分二叉树
- P1040 加分二叉树 记忆化搜索
- 洛谷P1040 加分二叉树(NOIP2003)
- [NOIP2003]区间dp-加分二叉树
- [区间DP]【NOIP2003T3】加分二叉树 题解
- Vijos P1100 加分二叉树(区间DP,树形DP)
- ACM 106. [NOIP2003] 加分二叉树(区间dp)
- 【基础练习】【区间DP】codevs1090 加分二叉树题解
- 《一个小时,学会黑客技能》——以前BiliBili上面的那个视频中的那个网站,我终于又找到了
- Linux之文件读写过程
- python __setitem__()方法理解
- js 在字符串中引入变量
- 第四天(Mysql数据库)
- P1040 加分二叉树(区间DP)
- 51nod 1500 苹果曼和树【树形DP】
- 用Nodejs的赶快把命令式编程的思维过度到函数式,看过太多坑代码了。
- 中文编码
- How to install Mediatek MT7630E wireless LAN driver in Linux Mint/Ubuntu
- 基于ESP8266的物联网解决方案
- 进程同步和异步--详解
- 关于API技术对接
- 如何在windows中使用cmd命令去编译,运行C++程序