题目描述
设一个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
其实还是比较水的题,因为是中序遍历,所以,根节点在中间,那么就是一个枚举根节点划分区间,有点像石子合并。
至于怎么求前序遍历,可以在递归的时候存储一遍,一旦更新值,就将祖先也更新处理,不是很难。
1 #include <iostream> 2 #include <fstream> 3 #include <cstdlib> 4 #include <cstring> 5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 6 using namespace std; 7 int cnt_node=0; 8 int gra_node[33]={0}; 9 int jiyi[33][33]={0}; 10 int root[33][33]={0}; 11 int dg(int ks,int js); 12 void out_DLR(int ks,int js); 13 14 15 int dg(int ks,int js){ 16 if(ks==js)return gra_node[ks]; 17 if(ks+1==js)return gra_node[ks]+gra_node[js]; 18 if(jiyi[ks][js]!=-1)return jiyi[ks][js]; 19 int tem=0; 20 tem=dg(ks+1,js)+gra_node[ks]; 21 root[ks][js]=ks; 22 for(int x=ks+1;x<js;x++){ 23 int b=dg(ks,x-1)*dg(x+1,js)+gra_node[x]; 24 if(b>tem){tem=b;root[ks][js]=x;} 25 } 26 int b=dg(ks,js-1); 27 if(b>tem){tem=b;root[ks][js]=js;} 28 jiyi[ks][js]=tem; 29 return tem; 30 } 31 32 33 void out_DLR(int ks,int js){ 34 if(ks==js){cout<<ks<<" ";return;} 35 if(ks+1==js){cout<<ks<<" "<<js<<" ";return;} 36 cout<<root[ks][js]<<" "; 37 out_DLR(ks,root[ks][js]-1); 38 out_DLR(root[ks][js]+1,js); 39 return; 40 } 41 42 43 int main(int argc, char** argv) { 44 cin>>cnt_node; 45 for(int x=1;x<=cnt_node;x++)cin>>gra_node[x]; 46 47 memset(jiyi,-1,sizeof(jiyi)); 48 int ans=dg(1,cnt_node); 49 cout<<ans<<endl; 50 out_DLR(1,cnt_node); 51 return 0; 52 }