-
描述
-
設一個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個用空格隔開的整數,為該樹的前序走訪。
-
範例輸入
-
55 7 1 2 100
-
範例輸出
-
1453 1 2 4 5
-
來源
-
NOIP 2003(BY Dyp)
題目中要求輸出分最高,需要進行排序,把分值大的盡量往葉子節點靠
#include <iostream>#define MAX 50using 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;}