CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树 /CodeVS 1090 加分二叉树
来源:互联网 发布:网络经营管理办法 编辑:程序博客网 时间:2024/05/20 17:08
CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树(树型动态规划)
Description
设 一个 n 个节点的二叉树 tree 的中序遍历为( 1,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 的前序遍历
Input
第 1 行:一个整数 n ( n < 30 ),为节点个数。
第 2 行: n 个用空格隔开的整数,为每个节点的分数(分数< 100 )。
Output
第 1 行:一个整数,为最高加分(结果不会超过 4,000,000,000 )。
第 2 行: n 个用空格隔开的整数,为该树的前序遍历。
Sample Input
5
5 7 1 2 10
Sample Output
145
3 1 2 4 5
Http
CJOJ:http://oj.changjun.com.cn/problem/detail/pid/1010
Luogu:https://www.luogu.org/problem/show?pid=1040
CodeVS:http://codevs.cn/problem/1090/
Source
树型动态规划
解决思路
因为题目给出的是中序遍历,所以有任意一棵子树的中序遍历一定是在一段里面的,我么令F[i][j]表示从i到j的最大加分,用Mayuri[i][j]表示i,j能得到最大加分的根节点。
那么我们可以枚举[i,j]之间的一个点k为根节点,得到状态转移方程F[i][j]=max(F[i][k-1]*F[k+1][j]+Value[k])同时更新Mayuri[i][j],最后的结果就是F[1][n]。
最后只输出,这里我们采用递归调用的方法,在主函数里调用Outp(1,n),对于Outp(i,j)来说,我们调用Outp(i,Mayuri[i]-1) Outp(Mayuri[i]+1,j),分别按照前序遍历输出。
需要注意的是各个变量的初始值赋值,具体请看代码。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int maxsize=100;const int inf=2147483647;int n;long long Node[maxsize];//存放每个点的权值long long F[maxsize][maxsize];//F[i][j]如题解中所示int Mayuri[maxsize][maxsize];//Mayuri[i][j]表示i,j这棵树的根节点void Outp(int l,int r);int main(){ memset(F,0,sizeof(F)); cin>>n; for (int i=1;i<=n;i++) cin>>Node[i]; for (int i=1;i<=n;i++) F[i][i-1]=1;//F[][]的初始化 for (int i=1;i<=n;i++) { F[i][i]=Node[i];//F的初始化 Mayuri[i][i]=i;//Mayuri的初始化 } for (int i=n;i>=1;i--) { for (int j=i+1;j<=n;j++) { for (int k=i;k<=j;k++) if (F[i][k-1]*F[k+1][j]+Node[k]>F[i][j]) { F[i][j]=F[i][k-1]*F[k+1][j]+Node[k]; Mayuri[i][j]=k; //cout<<"Update : "<<i<<' '<<j<<' '<<k<<' '<<F[i][j]<<endl; } } } cout<<F[1][n]<<endl; Outp(1,n);//递归输出前序遍历 cout<<endl; return 0;}void Outp(int l,int r){ if (l>r) return; cout<<Mayuri[l][r]<<' ';//因为是前序遍历,所以先输出根节点 if (l==r) return; Outp(l,Mayuri[l][r]-1);//递归调用 Outp(Mayuri[l][r]+1,r); return;}
- CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树 /CodeVS 1090 加分二叉树
- NOIP2003 加分二叉树
- [NOIP2003]加分二叉树
- #NOIP2003#加分二叉树
- 【noip2003】加分二叉树
- NOIP2003 加分二叉树
- Noip2003加分二叉树题解
- 【NOIP2003】加分二叉树题解
- noip2003 加分二叉树 dp
- NOIP2003 洛谷1040 加分二叉树
- 1090 加分二叉树
- 【树形DP】[NOIP2003]加分二叉树
- [NOIP2003]加分二叉树【动态规划】
- 【NOIP2003提高组】加分二叉树
- noip2003加分二叉树 2008.10.30
- 洛谷 P1040 [NOIP2003 T3] 加分二叉树
- NOIP2003提高组 加分二叉树
- 集训-加分二叉树[NOIP2003提高组]
- Shell 入门
- Jmeter正则表达式提取器(二)
- spring学习中遇到的坑之 xml约束导入问题
- [PyCV2]Win10 + OpenCV + Python + Numpy + matplotlib +Wing IDE环境搭建
- 华为机试:统计每个月兔子的总数、 字符串运用-密码截取
- CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树 /CodeVS 1090 加分二叉树
- 压缩解压缩linux命令(整理)
- Hibernate学习笔记(五)(Hibernate映射类型)
- Markdown编辑器使用-yellowcong
- PAT乙级1012. 数字分类 (20)
- 修改源码实现全局(无需root)注入躲开注入检测
- CCF2017-3-2 学生排队
- 移动端图片自适应
- EasyUI修改DateBox和DateTimeBox的默认日期格式,中文问题