http://www.luogu.org/problem/show?pid=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个用空格隔开的整数,为该树的前序遍历。

一开始写的是在算可以取得的最大值的时候计算每个节点的左右儿子,然而这个思路并不对...因为数据规模较小,DP求完最大值后可以再记忆化搜索一次来打印先序遍历,因为第一次已经求出了所有情况的值,所以第二次DP很快

 #include<iostream>
 #include<cstdio>
 #include<cstring>
 using namespace std;
 struct Node{
     int root;
     long long val;
 };
 ;
 long long mem[maxn][maxn];
 int v[maxn][maxn],lson[maxn],rson[maxn],num[maxn],fa[maxn][maxn],n;
 int init(){
     memset(v,,sizeof(v));
     memset(lson,,sizeof(lson));
     memset(rson,,sizeof(rson));
     memset(fa,,sizeof(fa));
 }
 Node dp(int l,int r){
     if(v[l][r]) return (Node){fa[l][r],mem[l][r]};
     v[l][r]=;
     ,tfa=-;
     if(l==r){
         mem[l][r]=num[l];
         fa[l][r]=l;
         return (Node){l,num[l]};
     }
     tfa=l;ans=dp(l+,r).val+num[l];
     ).val+num[r];
     if(x>ans) ans=x,tfa=r;
     ;i<r;i++){
         x=dp(l,i-).val*dp(i+,r).val+num[i];
         if(x>ans) ans=x,tfa=i;
     }
     ,r).root;
     ).root;
     else{
         lson[tfa]=dp(l,tfa-).root;
         rson[tfa]=dp(tfa+,r).root;
     }
     mem[l][r]=ans,fa[l][r]=tfa;
     return (Node){tfa,ans};
 }
 void print(int l,int r){
     if(l==r){
         printf("%d ",l);
         return;
     }
     ,r).val+num[l];int f=l;
     ).val+num[r];
     if(x>ans) ans=x,f=r;
     ;i<r;i++){
         x=dp(l,i-).val*dp(i+,r).val+num[i];
         if(x>ans) ans=x,f=i;
     }
     printf("%d ",f);
     if(f==l){
         print(l+,r);
     }else if(f==r){
         print(l,r-);
     }else{
         print(l,f-);
         print(f+,r);
     }
 }
 void dfs(int u){
     printf("%d ",u);
     if(lson[u]) dfs(lson[u]);
     if(rson[u]) dfs(rson[u]);
 }
 int main()
 {
     scanf("%d",&n);
     init();
     ;i<=n;i++) scanf("%d",&num[i]);
     printf(,n).val);
     //dfs(dp(1,n).root);
     print(,n);
     ;
 }

NOIP2003 加分二叉树的更多相关文章

  1. cogs 106. [NOIP2003] 加分二叉树(区间DP)

    106. [NOIP2003] 加分二叉树 ★☆   输入文件:jfecs.in   输出文件:jfecs.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 设 一个 n ...

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

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

  3. 【题解】NOI2009二叉查找树 + NOIP2003加分二叉树

    自己的思维能力果然还是太不够……想到了这棵树所有的性质即中序遍历不变,却并没有想到怎样利用这一点.在想这道题的过程中走入了诸多的误区,在这里想记录一下 & 从中吸取到的教训(原该可以避免的吧) ...

  4. NOIP-2003 加分二叉树

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

  5. NOIP2003加分二叉树

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

  6. CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树(树型动态规划)

    CJOJ 1010[NOIP2003]加分二叉树 / Luogu 1040 加分二叉树(树型动态规划) Description 设 一个 n 个节点的二叉树 tree 的中序遍历为( 1,2,3,-, ...

  7. 加分二叉树 vijos1991 NOIP2003第三题 区间DP/树形DP/记忆化搜索

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

  8. CODEVS1090 加分二叉树

    codevs1090 加分二叉树 2003年NOIP全国联赛提高组 题目描述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点 ...

  9. Vijos 1100 加分二叉树

    题目 1100 加分二叉树 2003年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB   题目描述 Description 设一个n个节点的二叉树tree的中序遍历为( ...

随机推荐

  1. Env:VIM配置

    注:文章来自于http://www.cnblogs.com/ma6174/archive/2011/12/10/2283393.html 花了很长时间整理的,感觉用起来很方便,共享一下. 我的vim配 ...

  2. 反转(开关问题) POJ 3276

    POJ 3276 题意:n头牛站成线,有朝前有朝后的的,然后每次可以选择大小为k的区间里的牛全部转向,会有一个最小操作m次使得它们全部面朝前方.问:求最小操作m,再此基础上求k. 题解:1.5000头 ...

  3. JavaScript中对于闭包的理解

    1.什么是闭包? 闭包,官方对闭包的解释是:一个拥有很多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 闭包的特点: (1).作为一个函数变量的一个引用,当函 ...

  4. solace

    最近做了一个关于solace的项目,有时间来总结一下 1>. solace 介绍 2>. solace 应用(C#)

  5. sql语句(mysql)

    MySQL1.数据库数据类型 int 整型 double 浮点型 如double(5,2)最多5位,其中有两位小数 char:固定长度字符串,如char(255),数据长度不足会用空格补足 varch ...

  6. MongoDB项目中常用方法

    使用MongoDB连接池MongoOptions来进行连接 以及相关方法的调用 //获得驱动地址(这里的驱动 写入了配置文件中) String serverAddressStr = Configure ...

  7. php pcntl 多进程学习

    1.捕获子进程退出(监听SIGCHLD信号,然后调用 pcntl_wait 函数) declare(ticks=1); pcntl_signal(SIGCHLD, "sig_handler& ...

  8. python(21)实现多进程

    参考链接:http://www.cnblogs.com/kaituorensheng/p/4445418.html python多进程:multiprocessing python中的多线程其实并不是 ...

  9. MVC ViewData和ViewBag[转]

    转自:http://blog.csdn.net/a497785609/article/details/7854402#t0       视图数据可以通过ViewBag属性访问,它主要是为了从Contr ...

  10. Ubuntu下启动Apache的Rewrite功能

    在终端中执行 sudo a2enmod rewrite 指令后,即启用了 Mod_rewrite 模块. 另外,也可以通过将 /etc/apache2/mods-available/rewrite.l ...