洛谷1040加分二叉树【NOIP2003普及组】
2016-05-14 09:47
351 查看
题目描述
设一个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的最大得分,则取其根为k,f[i][j]=max{f[i][k-1]*f[k+1][j]+a[k]},i<=k<=j
由于要输出先序遍历,所以顺便记一下根节点k,输出时再分治即可。
#include<cstdio> #include<cstring> int a[35],f[35][35],r[35][35]; int max(int x,int y) { return x>y?x:y; } void prt(int i,int j) { int k,p,q,x,y,z; if (i>j) return; printf("%d ",r[i][j]); prt(i,r[i][j]-1); prt(r[i][j]+1,j); } int main() { int i,j,k,l,m,n,p,q,x,y,z,mid; scanf("%d",&n); for (i=1;i<=n;i++) scanf("%d",&a[i]); for (i=1;i<=n;i++) { f[i][i]=a[i]; r[i][i]=i; } for (l=2;l<=n;l++) for (i=1;i+l-1<=n;i++) { j=i+l-1; if (a[i]+f[i+1][j]>=a[j]+f[i][j-1]) { f[i][j]=a[i]+f[i+1][j]; r[i][j]=i; } else { f[i][j]=a[j]+f[i][j-1]; r[i][j]=j; } for (k=i+1;k<=j-1;k++) if (f[i][k-1]*f[k+1][j]+a[k]>f[i][j]) { f[i][j]=f[i][k-1]*f[k+1][j]+a[k]; r[i][j]=k; } } printf("%d\n",f[1] ); prt(1,n); }
相关文章推荐
- 【Web】Javascript、Python、Django模板配合处理URL Encode
- 【BZOJ2660】[Beijing wc2012]最多的方案【找规律】【计数DP】【二进制】【Fibonacci】
- 求最长等差数列长度
- LeetCode刷题之旅(6)
- Java 秒转mm:ss 格式
- 有趣的通讯录—<静态版>
- 递归和尾递归的比较,斐波那契
- 常用排序算法总结(五)
- sqlite基本sql语句使用
- matlab文件IO(读取写入)2 低级例程
- ...python の 学习
- 动态创建Lambda表达式实现高级查询
- 初见android
- 常用排序算法总结(四)
- 颜色代码大全
- Servlet获取表单提交过来的数据
- 前++和后++引发的血案~~!!
- C/C++ 堆与栈的区别
- 运行时的多态与多重继承
- ACM 搜索 hdu1010 Tempter of the Bone