背景

NOIP2003 提高组 第三道

描述

设一个n个节点的二叉树tree的中序遍历为(l,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的前序遍历

输入格式

第1行:一个整数n(n<30),为节点个数。
    第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。

输出格式

第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。
    第2行:n个用空格隔开的整数,为该树的前序遍历。

测试样例1

输入


5 7 1 2 10

输出

145 
3 1 2 4 5

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,f[][],p[][],v[]; void print(int l,int r){
printf("%d ",p[l][r]);
if(l<=p[l][r]-) print( l ,p[l][r]-);
if(p[l][r]+<=r) print( p[l][r]+ ,r );
} int dp(int l,int r){
if(l>r) return ;
if(l==r){
p[l][r]=l;
return v[l];
}
if(f[l][r]>=) return f[l][r]; for(int k=l;k<=r;k++){
if(dp(l,k-)*dp(k+,r)+v[k]>f[l][r]){
f[l][r]=dp(l,k-)*dp(k+,r)+v[k];
p[l][r]=k;
}
}
return f[l][r];
} int main(){
// freopen("01.txt","r",stdin);
memset(f,-,sizeof(f));
scanf("%d",&N);
for(int i=;i<=N;i++) scanf("%d",&v[i]); printf("%d\n",dp(,N));
print(,N);
puts(" "); return ; }

额,这一题耗了我很久时间,原因是二叉树问题没搞懂:

不懂的童鞋看这里:二叉树遍历入门之入门(http://www.cnblogs.com/radiumlrb/p/5790331.html)

刚写的

差不多看完就知道这题怎么做的了!

p数组记录路径,f记录当前子树根节点

dp函数算最大值并记录路径

print函数打印路径

TYVJ P1073 加分二叉树 Label:区间dp的更多相关文章

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

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

  2. 【Luogu】P1040加分二叉树(区间DP)

    题目链接 区间DP,因为中序遍历的性质:区间[l,r]的任何一个数都可以是该区间的根节点. 更新权值的时候记录区间的根节点,最后DFS输出. 见代码. #include<cstdio> # ...

  3. P1040 加分二叉树(区间DP)

    (点击此处查看原题) 解题思路 题目已经给出了树的中序遍历,因此我的想法是利用中序遍历的特点:若某子树的根结点为k,那么k之前的结点组成这一子树的左子树,k之后的结点组成这一子树的右子树,可以通过不断 ...

  4. TYVJ P1078 删数 Label:区间dp

    描述 有N个不同的正整数数x1, x2, ... xN 排成一排,我们可以从左边或右边去掉连续的i个数(只能从两边删除数),1<=i<=n,剩下N-i个数,再把剩下的数按以上操作处理,直到 ...

  5. 洛谷P1040 加分二叉树(树形dp)

    加分二叉树 时间限制: 1 Sec  内存限制: 125 MB提交: 11  解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...

  6. tyvj 1198 矩阵连乘——区间dp

    tyvj 1198 矩阵连乘 题目描述 一个n*m矩阵由n行m列共n*m个数排列而成.两个矩阵A和B可以相乘当且仅当A的列数等于B的行数.一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算 ...

  7. TYVJ P1047 乘积最大 Label:dp

    背景 NOIP 2000 普及组 第三道 描述 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力 ...

  8. TYVJ P1075 硬币游戏 Label:dp

    背景 农民John的牛喜欢玩硬币,所以John就为它们发明了一个新的两人硬币游戏,叫做Xoinc. 描述 最初地面上有一堆n个硬币(5<=n<=2000),从上面数第i个硬币的价值为C_i ...

  9. VJP1100 加分二叉树(树形DP)

    链接 归属树形DP  做着更像记忆化 DP很好做 就是那个输出路径恶心了..改代码 从60多行改到120多行..dp从1维加到三维.. 先类似记忆化搜索整棵树 枚举以i为根节点的最大值 子树类似 求完 ...

随机推荐

  1. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  2. sass的视频教程

    http://www.w3ci.com/video/715.html http://koala-app.com/index-zh.html /***************三角形的应用******** ...

  3. TokuDB的特点验证

    随着数据量越来越大,越来越频繁的遇到需要进行结构拆分的情况,每一次拆分都耗时很久,并且需要多方配合,非常的不想搞这个事情.于是在@zolker的提醒下想到了13年开源tokuDB,来解决我们迫在眉睫的 ...

  4. poj 2739 Sum of Consecutive Prime Numbers 解题报告

    题目链接:http://poj.org/problem?id=2739 预处理出所有10001以内的素数,按照递增顺序存入数组prime[1...total].然后依次处理每个测试数据.采用双重循环计 ...

  5. HDU1250 高精度斐波那契数列

    Hat's Fibonacci Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  6. [Java] Java 打包成jar包 和 解压jar包

    解压jar包 jar xf xxx.jar 打包成jar包 方法一:通过jar命令 jar命令的用法: 下面是jar命令的帮助说明: 用法:jar {ctxui}[vfm0Me] [jar-file] ...

  7. 正则和xml解析

    一般来说是xml解析的开销比正则大些.使用正则搜索,只需搜索<second>就能定位到你要的内容,而xml解析要把节点树在内存中建立起来,所以消耗内存会多些,速度可能会受到一些影响.但对于 ...

  8. javascript ASCII和Hex互转

    <script> var symbols = " !\"#$%&'()*+,-./0123456789:;<=>?@"; var loAZ ...

  9. Paths on a Grid(poj 1942)

    给定一个矩形网格的长m和高n,其中m和n都是unsigned int32类型,一格代表一个单位,就是一步,求从左下角到右上角有多少种走法,每步只能向上或者向右走. //注意循环的时候,要循环小的数,否 ...

  10. 【Ubuntu14.04.1】设置开机可以Root用户身份登录

    $ sudo gedit /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf [SeatDefaults]user-session=ubuntugreet ...