バイナリポイント(インターバルDP、木DP)

nnは(1,2,3、...、n1,2,3、...、N)として予約購入のノードのバイナリツリーを設ける場合数1,2,3、...、n1,2,3、... 、nはノードの数です。各ノードは、第二の画分と呼ばれるスコア(共に正の整数)を有するIIノードジ、treedi、木であり、そのサブツリーの各々は、任意のサブツリーsubtreesubtreeを有するプラス(それ自体も含むtreetree)次のようにボーナスが計算されます。

subtreesubtreeのルートポイント+留分の左部分木のsubtreesubtree部分×subtreesubtree右部分木の。

サブツリーが空である場合、11に加え、葉スコア余分なポイントに分割された規定は、リーフノード自体です。その空の木のに関わらず。

予約購入を決定する(...、1,2,3、...、n1,2,3、N)に準拠して、バイナリツリーtreetreeの最高点。必要な出力;

(1)treetree最高点

(2)treetree Aプレオーダートラバーサル

入力形式

行11:11の整数N(N <30)、N(N <30)、ノードの数です。

ライン22は:NN整数画分(画分<100 <100)のように、スペースで各ノードを分離しました。

出力フォーマット

11行目:11個の整数、最高点(ANS \ル4,000,000,000≤4,000,000,000)。

22行目:NN整数は、ツリーの先行順走査のために、スペースで区切られています。

サンプル入力と出力

入力#1コピー

5 
5 7 1 2 10

出力#1コピー

145 
3 1 2 3 4 5

アイデア:

  1. 左のサブツリーをトラバースするために左ルーツ、右の右のサブツリーです
  2. オーダートラバーサルシーケンス内のサブツリーには、まだrootとして、左の部分木は右の右部分木があり、残っています
  3. 最大のポイントサブバイナリツリー、バイナリツリーはまた、最大のプラスポイントです
  4. したがって、間隔DPとみなし、及び再帰式を描くことができる:DP [I] [J] = MAX(DP [I]、[J]、DP [i]は[M-1] * DP [M + 1] [J] + DP [M] [M]); DP [I] [j]は点の最大シーケンスを表す私は〜jは、mは数列挙ルート、I〜Jの範囲であり、バイナリツリーを形成することができます
#include<iostream>
#include<algorithm>
using namespace std;
int n,mid[32][32]={0},dp[32][32];
void first(int x,int y){  //先序遍历区间X~Y,并输出序列 
	if(x==y){
		cout<<" "<<x;
		return;
	}
	if(y<x)return ;
	cout<<" "<<mid[x][y];
    first(x,mid[x][y]-1);
    first(mid[x][y]+1,y);
}
int main() {
	cin>>n;
	for(int i=0; i<=n; i++)
		fill(dp[i],dp[i]+n+2,1);
	for(int i=1; i<=n; i++)
		cin>>dp[i][i],mid[i][i]=i;
	for(int k=1; k<n; k++) {   //枚举区间大小 ,k表示间隔大小 
		for(int i=1,j=i+k; j<=n; i++,j++) {  //枚举区间起始和终点 
			for(int m=i; m<=j; m++) {  //枚举树根 
				int t=dp[i][m-1]*dp[m+1][j]+dp[m][m];  //递推式 
				if(dp[i][j]<t){
					dp[i][j]=t;
					mid[i][j]=m;  //存储树根 
				}
			}
		}
	}cout<<dp[1][n]<<endl;  //区间i到n的最大加分二叉树大小 
	cout<<mid[1][n];//输出区间1~n的树根 
	first(1,mid[1][n]-1);  //输出区间1~n-1的所有树根 
	first(mid[1][n]+1,n);
	return 0;
}

 

公開された42元の記事 ウォン称賛16 ビュー3403

おすすめ

転載: blog.csdn.net/qq_41542638/article/details/99656008