Binary points (interval DP, tree DP)

Nn is provided a binary tree of nodes in preorder as (1,2,3, ..., n1,2,3, ..., n), where the number 1,2,3, ..., n1,2,3, ... , n is a node number. Each node has a score (both positive integers), referred to the second fraction ii node is di, treedi, tree and each of its sub-tree has a plus, any subtree subtreesubtree (itself also comprises treetree) the bonus is calculated as follows:

Of the left subtree subtreesubtree partial × subtreesubtree right subtree of the root points + fraction of subtreesubtree.

If a sub-tree is empty, the provisions of which are divided into 11 plus, leaves scores extra points is the leaf node itself. Irrespective of its empty tree.

Determine a preorder conform to (1,2,3, ..., n1,2,3, ..., n) and the highest points of the binary tree treetree. Required output;

(1) treetree highest points

(2) treetree a preorder traversal

Input Format

Line 11: 11 integer n (n <30) n (n <30), is the number of nodes.

Line 22: nn integers separated by spaces, each node as a fraction (fraction <100 <100).

Output Format

Line 11: 11 integers, the highest points (Ans \ le 4,000,000,000≤4,000,000,000).

Line 22: nn integers separated by spaces, for preorder traversal of the tree.

Sample input and output

Input # 1 copy

5
5 7 1 2 10

Output # 1 copy

145
3 1 2 4 5

Ideas:

  1. Roots left in order to traverse the left subtree, right is right subtree
  2. In sub-tree in order traversal sequence, still as a root, left subtree is left, right is right subtree
  3. The maximum points a sub binary tree binary tree is also the biggest plus points
  4. Thus it can be regarded as the interval DP, and draw recursive formula: dp [i] [j] = max (dp [i] [j], dp [i] [m-1] * dp [m + 1] [j] + dp [m] [m]); dp [i] [j] represents the maximum sequence of points i ~ j may form a binary tree, m is a number enumeration root, the range of 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;
}

 

Published 42 original articles · won praise 16 · views 3403

Guess you like

Origin blog.csdn.net/qq_41542638/article/details/99656008