加分二叉树

描述

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

样例输入1[复制]

 
5
5 7 1 2 10

样例输出1[复制]

 
145
3 1 2 4 5

限制

每个测试点1s

来源

NOIP2003第三题

 

 

都说是DP。。。我开始想的是暴力。。。然后瞎写了写怎么就写了个DP。。。。

我的想法是因为n最多只有30个。。那么我们可以枚举根节点,然后分别在根的两边进行同样的操作。。。然后就变成了枚举区间枚举节点。。。

不过枚举区间的时候要记住从后往前。。。

 4 #include<iostream>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 #include<cstdio>
 9 #include<algorithm>
10 #include<string>
11 #include<map>
12 #include<queue>
13 #include<vector>
14 #include<set>
15 #define inf 1000000000
16 #define maxn 100+5
17 #define maxm 100+5
18 #define eps 1e-10
19 #define ll long long
20 #define for0(i,n) for(int i=0;i<=(n);i++)
21 #define for1(i,n) for(int i=1;i<=(n);i++)
22 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
23 #define for3(i,x,y) for(int i=(x);i>(y);i--)
24 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
25 using namespace std;
26 int read()
27 {
28     int x=0,f=1;char ch=getchar();
29     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
30     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
31     return x*f;
32 }
33 int f[maxn][maxn],a[maxn],root[maxn][maxn];
34 void output(int l,int r){
35     if(l>r)return;
36     printf("%d ",root[l][r]);
37     output(l,root[l][r]-1);
38     output(root[l][r]+1,r);
39 }
40 int main(){
41     freopen("input.txt","r",stdin);
42     freopen("output.txt","w",stdout);
43     int n=read();
44     f[0][0]=1;
45     for1(i,n)
46         root[i][i]=i;
47     for1(i,n)f[i][i]=a[i]=read(),f[i][i-1]=1; 
48     for3(i,n,0)
49         for2(j,i+1,n){
50             for2(k,i,j){
51                 if(f[i][j]<f[i][k-1]*f[k+1][j]+f[k][k]){
52                     root[i][j]=k;
53                     f[i][j]=f[i][k-1]*f[k+1][j]+f[k][k];
54                 }
55             }
56         }
57     printf("%d\n",f[1][n]);
58     output(1,n);
59     return 0;
60 }
View Code

 

posted @ 2016-02-01 16:25  HTWX  阅读(127)  评论(0编辑  收藏  举报