已知二叉树中序遍历序列,求所有可行树中的某种状态最优解。
二叉树中序遍历性质:1.遍历顺序:左节点->根->右节点。2.序列最后一个元素与深度遍历(二叉树前序遍历)时的最后一个元素相同3.同一个子树的遍历顺序是一个连续序列,此序列中的某个点都可能是该子树的根节点
dp[i][j]:[i,j]序列中的最优解。根据性质3,必须枚举所有可能的子节点。pre[i][j]:[i,j]序列子树的根节点是k
dp[i][j]=max{dp[i][k-1]*dp[k+1][j]+w[k]} pre[i][j]=k
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#define ll long long
#define sf scanf
#define pf printf
#define maxn 50
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
const ll mod=1000000007;
using namespace std;
int n,w[maxn],pre[maxn][maxn],dp[maxn][maxn];
void print(int i,int j){
if(i>j) return;
printf("%d",pre[i][j]);
if(i!=j||i!=n) printf(" ");
print(i,pre[i][j]-1);
print(pre[i][j]+1,j);
}
int main(){
scanf("%d",&n);
mem(dp,0),mem(pre,-1);
for(int i=1;i<=n;i++) scanf("%d",&w[i]),dp[i][i]=w[i],pre[i][i]=i;
for(int l=1;l<=n-1;l++){
for(int i=1;i+l<=n;i++){
int j=i+l;
for(int k=i;k<=j;k++){
if(dp[i][k-1]*dp[k+1][j]+w[k]>dp[i][j]){
if(k-1<i) dp[i][k-1]=1;
if(k+1>j) dp[k+1][j]=1;
dp[i][j]=dp[i][k-1]*dp[k+1][j]+w[k];
pre[i][j]=k;
}
}
}
}
printf("%d\n",dp[1][n]);
print(1,n);
printf("\n");
}