1078 加分二叉树

 
描述

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

输入

有若干组测试数据,每组测试数据有两行:第1行:一个整数n(n<30),为节点个数。第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。测试数据最后以0结尾。

输出

每组测试数据的第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。第2行:n个用空格隔开的整数,为该树的前序遍历。

样例输入
5
5 7 1 2 10
0




样例输出
145
3 1 2 4 5





来源
NOIP 2003(BY Dyp)

 

题目中要求输出分最高,需要进行排序,把分值大的尽量往叶子节点靠

 

#include <iostream>
#define MAX 50

using namespace std;

unsigned long F[MAX][MAX];
int root[MAX][MAX];
int N;

void init()
{
	int i,j;
	
	
	cin >> N;
	if(N!=0)
	{

	
	for (i=0;i<=N+1;i++)
		for (j=0;j<=N+1;j++)
			F[i][j]=-1;
		for (i=1;i<=N;i++)
		{
			cin >> F[i][i];
			root[i][i]=i;
		}
	}
}

unsigned long dynamic(int a,int b)
{
	if (a>b)
		return 1;
	int k;
	unsigned long A=0;
	for (k=a;k<=b;k++)
	{
		if (F[a][k-1]==-1)
			F[a][k-1]=dynamic(a,k-1);
		if (F[k+1][b]==-1)
			F[k+1][b]=dynamic(k+1,b);
		if (F[a][k-1]*F[k+1][b]+F[k][k] > A)
		{
			A=F[a][k-1]*F[k+1][b]+F[k][k];
			root[a][b]=k;
		}
	}
	return A;
}

void scan(int a,int b)
{
	if (a>b)
		return;
	int p=root[a][b];
	cout << p << ' ';

	scan(a,p-1);
	scan(p+1,b);
}

int main()
{  

	init();
	 
	while(N!=0)
	{

	
	F[1][N]=dynamic(1,N);
	cout << F[1][N] << endl;
	scan(1,N);
		cout<<endl;
		init();
	}
	
	return 0;
}


 

你可能感兴趣的:(1078 加分二叉树)