题目描述

设一个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个用空格隔开的整数,为该树的前序遍历。

输入输出样例

输入样例#1

5

5 7 1 2 10

输出样例#1

145

3 1 2 4 5

算法:

区间DP

 

分析:

这个10多年前的提高组试题其实也不算太难,但是有很多要注意的小点。

首先这道题上手先分析感觉和树形DP有点关系,然而再看清楚一点呢,就发现它其实只是在区间上dp,然而树只是对它的一个约束。

我们先来简化题目,假如我问的是在一个区间上求最大加分,那么这个状态转移方程应该很容易得到,就是f[i][j]=max(f[i][k-1]*f[k+1][j]+a[k])其中表示从i到j的区间最大值,k满足i<=k<=j。

注意这里可以取等。

 

接下来,有一个性质:

对于任意二叉树,其中序遍历中的任意一段区间的根节点可以是任何一个节点。

 

那么问题解决。

 

这个就可以直接套用到区间DP中,不过还要记录下相应的i,j的根节点是什么。最后输出先序遍历的过程其实就是dfs的思想,加一个记忆化搜索会提高效率。

 

要点注意:

1、为了方便调试,可以将数组开到6,但注意要调回正常值在提交

2、存答案的数组要用long long,否则会wa

3、记忆化部分要确定有值(非空子树)才递归下去

4、初始化答案数组f要放在输入前

5、注意要先定好某次递推的区间长度,否则会找到没运算过的值。

上代码:

 #include<cstdio>
#include<iostream>
using namespace std; long long f[][]; //注意要用超长整型
int n,r[][],a[],fl=; inline int read()
{
int x=,f=;
char c=getchar();
while (c<||c>)
f=c=='-'?-:,c=getchar();
while (c>=&&c<=)
x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
} void tree(int lt,int rt)
{
if (r[lt][rt]) //某些oj会判结尾为空格的情况
{
if (!fl)
printf("%d",r[lt][rt]),fl=;
else
printf(" %d",r[lt][rt]);
}
if (r[lt][r[lt][rt]-]) //递归左子树
tree(lt,r[lt][rt]-);
if (r[r[lt][rt]+][rt]) //递归右子树
tree(r[lt][rt]+,rt);
} int main()
{
int i,j,k,len;
n=read();
for (i=;i<=n;i++) //初始化为1,注意不可以memset
for (j=;j<=n;j++)
f[i][j]=;
for (i=;i<=n;i++)
{
a[i]=read();
f[i][i]=a[i]; //每个点自己作为叶子节点时,
r[i][i]=i; //根节点就是自己
}
/* //注意这种方法不可取
for (i=1;i<=n-1;i++)
for (j=i+1;j<=n;j++)
{
long long tmp=INF;
for (k=i;k<=j;k++)
if (tmp<f[i][k-1]*f[k+1][j]+a[k])
{
tmp=f[i][k-1]*f[k+1][j]+a[k];
r[i][j]=k;
}
f[i][j]=tmp;
}
*/
for (len=;len<=n;len++) //先定区间长度
for (i=;i+len<=n;i++) //设起点,i+len为终点
{
long long tmp=-; //没必要太小
for (k=i;k<=i+len;k++) //寻根
if (tmp<f[i][k-]*f[k+][i+len]+a[k])
{
tmp=f[i][k-]*f[k+][i+len]+a[k];
r[i][i+len]=k;
}
f[i][i+len]=tmp;
}
printf("%lld\n",f[][n]);
tree(,n);
return ;
}

讲讲memset为什么不行,因为在c++中memset是按位来赋值的,一个int是4位,一个long long是8位(好像是吧),所以一次就会推了8个1,而不是想要的一个1。而对于清零和赋极值memset是很好用的。

 

嗯,就这样了。

【NOIP2013提高组T3】加分二叉树的更多相关文章

  1. 【NOIP2003提高组】加分二叉树

    https://www.luogu.org/problem/show?pid=1040 令f(i,j)表示[i,j]的二叉树中最高的分数.枚举k为根,状转方程:f(i,j)=max{f(i,k-1)* ...

  2. [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路

    [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...

  3. JZOJ2020年8月11日提高组T3 页

    JZOJ2020年8月11日提高组T3 页 题目 Description 战神阿瑞斯听说2008年在中华大地上,将举行一届规模盛大的奥林匹克运动会,心中顿觉异常兴奋,他想让天马在广阔的天空上,举行一场 ...

  4. 【GDKOI2014】JZOJ2020年8月13日提高组T3 壕壕的寒假作业

    [GDKOI2014]JZOJ2020年8月13日提高组T3 壕壕的寒假作业 题目 Description Input Output 输出n行.第i行输出两个整数,分别表示第i份作业最早完成的时刻以及 ...

  5. JZOJ2020年8月10日提高组T3 玩诈欺的小杉

    JZOJ2020年8月10日提高组T3 玩诈欺的小杉 题目 Description 是这样的,在小杉的面前有一个N行M列的棋盘,棋盘上有\(N*M\)个有黑白棋的棋子(一面为黑,一面为白),一开始都是 ...

  6. 【佛山市选2013】JZOJ2020年8月7日提高组T3 海明距离

    [佛山市选2013]JZOJ2020年8月7日提高组T3 海明距离 题目 描述 对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数.异或的规则为: 0 XOR 0 = 0 1 XOR ...

  7. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  8. [NOIP2013 提高组] 华容道 P1979 洛谷

    [NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...

  9. [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...

随机推荐

  1. OSG学习:用多通道(multiple passes)实现透明度

    osgFX库提供了一个用于多通道渲染(multi-pass rendering)的框架.每个你想要渲染的子图都应该被添加到osgFX::Effect节点,多通道技术的定义和使用都可以在这个节点中完成. ...

  2. PictureBox使用异常

    PictureBox的使用 代码: 显示部分 当我切换不同位置之间的照片时,出现这种问题: 但是当我代码改成下面的代码时,则错误消除 但我并不清楚原因

  3. delphi 事务处理SQL语句

    方法一(利用adoconnection.exe(sqlstate)): adoconnection1.begintrans;//开始事务try adoconnection1.execute(sqlst ...

  4. 第123天:移动web开发中的常见问题

    一.函数库 underscoreJS _.template: <ol class="carousel-indicators"> <!--渲染的HTML字符串--& ...

  5. SQL Server Management Studio(SSMS)的使用与配置整理

    目录 目录 SQL Server Management Studio的使用与配置 1 设置SSMS显示行号 2 添加注释与取消注释的快捷键 3 新建查询的快捷键 4 开启sql语句TIME与IO的统计 ...

  6. 深入理解JVM一java堆分析

    上一节介绍了针对JVM的监控工具,包括JPS可以查看当前所有的java进程,jstack查看线程栈可以帮助你分析是否有死锁等情况,jmap可以导出java堆文件在MAT工具上进行分析等等.这些工具都非 ...

  7. 【题解】CF#611 H-New Year and Forgotten Tree

    有趣啊~手玩一下这棵树,发现因为连边只对相连点的位数有限制,我们可以认为是在往一棵已经有 m 个结点的树上挂叶子结点直到满足要求.(m = log(10) n).注意由于 m 超级无敌小,我们可以直接 ...

  8. 【ZOJ3316】Game(带花树)

    [ZOJ3316]Game(带花树) 题面 Vjudge 翻译: 给定棋盘上\(n\)个旗子 一开始先手可以随便拿, 然后每次都不能取离上次的曼哈顿距离超过\(L\)的旗子 谁不能动谁输. 问后手能否 ...

  9. 测试开发面试的Linux面试题总结之一:vim使用方法

    现在做测试没有说不用到linux,大部分公司都会涉及到,作为测试经常使用linux最常见手段就是查看日志,帮助开发定位问题,这是目前最常见的测试当中使用linux方法,今天就讲一讲vim文本编辑器的使 ...

  10. redis分布式(主从复制)

    Redis主从复制配置和使用都非常简单.通过主从复制可以允许多个slave server拥有和master server相同的数据库副本.    Redis的复制原理:本身就是Master发送数据给s ...