CODEVS1090加分二叉树 noip提高组T32003

题目描述 Description

设一个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的前序遍历

现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

思路: 比较简单的树形dp,每次都穷举根节点,然后简单的递归。不过第一件比较。。。的事情就是输出路径,可以用最短路时的思路,保存l、r为左右端点的根节点,然后递归输出。第二件比较。。。的事情就是要判断是否该区间已有值,若有值就一定是最优值,不需要在穷举了,为了这个tle了两个点。。。我醉了。。。

code:

#include<iostream>

#include<cstdio>

using namespace std;

long long f[50][50]={0};

int a[50]={0},path[50][50]={0};

void print(int l,int r)

{

if (l>r) return;

if (path[l][r]!=0)

{

printf("%d ",path[l][r]);

print(l,path[l][r]-1);

print(path[l][r]+1,r);

}

}

void work(int l,int r)

{

int j;

if (l>r)

{

f[l][r]=1;

path[l][r]=0;

return;

}

if (f[l][r]!=0) return;

if (l==r)

{

f[l][r]=a[l];

path[l][r]=l;

return;

}

for (j=l;j<=r;++j)

{

work(l,j-1);

work(j+1,r);

if (f[l][j-1]*f[j+1][r]+a[j]>f[l][r])

{

f[l][r]=f[l][j-1]*f[j+1][r]+a[j];

path[l][r]=j;

}

}

}

int main()

{

int i,j,n;

scanf("%d",&n);

for (i=1;i<=n;++i)

scanf("%d",&a[i]);

work(1,n);

printf("%d\n",f[1][n]);

print(1,n);

cout<<endl;

}

时间: 2024-08-13 10:49:41

CODEVS1090加分二叉树 noip提高组T32003的相关文章

Vijos P1002 过河 (NOIP提高组2005)

链接:https://www.vijos.org/p/1002 解析: 若 p*x+(p+1)*y=Q(采用跳跃距离p和p+1时可以跳至任何位置Q),则在Q ≥ P*(P-1)时是一定有解的. 由于题目给出的一个区间是1≤S≤T≤10,于是当相邻的两个石子之间的距离不小于8*9=72时,则后面的距离都可以到达,我们就可以认为它们之间的距离就是72.如此一来,我们就将原题L的范围缩小为了100*72=7200,动态规划算法完全可以承受了. 但是当S=T时,上述等式是无法使用的,在这种情况下,只需要

NOIP提高组2004 合并果子题解

NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了.多多在合并果子时总共消耗的体力等于每次合并所耗体力之和. 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力.假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出

NOIP 提高组2013 火柴排队 (Vijos P1842)

描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑ i=1 n (a i ?b i ) 2  ,其中 a i   表示第一列火柴中第 i 个火柴的高度,b i   表示第二列火柴中第 i 个火柴的高度. 每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小.请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模

NOIP提高组 1999 &amp; 2000 题解合集

[序言]话说我在学神奇算法的时候,基础应该也要巩固,于是打算提前把NOIP提高组的刷完. 具体的题目描述和提交我就在VIJOS上完成. [1999.1] 描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1-max之间的每一个邮资值都能得到. 例如,N=3,M=2,如果面值分别为1分.4分,则在l分-6分之间的每一个邮资值都能得到(当然还有8分.9分和12分):如果面值分别为1分.3分

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c

2017.12.02【NOIP提高组】模拟赛A组

2017.12.02[NOIP提高组]模拟赛A组 T1 3555[GDKOI2014模拟]树的直径 T2 3542[清华集训2014]冒泡排序 T3 3486[NOIP2013模拟联考10]道路改建(rebuild) T1 树直径的一个性质,两棵树合并,形成新的树的直径的两个端点为原树中的四个端点之二. 可以用反证法证明.用此性质本题就变成了lca裸题了 Code #include<cstdio> #include<cstring> #include<cmath> #i

2017.12.09【NOIP提高组】模拟赛A组

2017.12.09[NOIP提高组]模拟赛A组 T1 3489. [NOIP2013模拟联考11]数列的GCD(gcd) T2 3500.[NOIP2013模拟联考15]物语(monogatari) T3 3501.[NOIP2013模拟联考15]消息传递(news) 吐槽:这次的题好像有点水啊,但最简单的第二题都给打挂啦!!(数组开小了) T1 本套题中最难的题.考虑dp 设f[i]是b[1],b[2]...b[N]的最大公约数的数目,g[i]是b[1],b[2]...b[N]的公约数的数目

2015 Noip提高组 Day1

P2615 神奇的幻方 [题目描述] 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. 之后,按如下方式从小到大依次填写每个数K(K=2,3,…,N*N): 1.若(K−1)在第一行但不在最后一列,则将K填在最后一行,(K−1)所在列的右一列: 2.若(K−1)在最后一列但不在第一行,则将K填在第一列,(K−1)所在行的上一行: 3.若(K−1)在第一行最

【基础练习】【区间DP】codevs1090 加分二叉树题解

2003 NOIP TG 题目描写叙述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),当中数字1,2,3,-,n为节点编号.每一个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每一个子树都有一个加分,任一棵子树subtree(也包括tree本身)的加分计算方法例如以下: subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数 若某个子树为主,规定其加分为1,叶子的加分就是叶节点本身的分数. 不考