唉 天天摸鱼导致一感冒 好点后再写题解都超时了
虽然没牛币可以白嫖但还是写写自己的理解吧
这题我们要抓住中序遍历的特点 以根节点划分左子树右子树
这样就可以不断递归下去求
解法就出来了 区间dp dp[i][j]表示i-j区间二叉树划分的分数最大
前序遍历就是每次求最大时记录下根节点即可

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 35;
int dp[N][N],pre[N][N],a[N],n;
void dfs(int l,int r) {
    if(l>r) return;
    int k=pre[l][r];
    cout<<k<<" ";
    dfs(l,k-1);
    dfs(k+1,r);
}
int main() {
    cin>>n;
    for(int i=0;i<=n;++i)
     for(int j=0;j<=n;++j)
          dp[i][j]=1;
    for(int i=1;i<=n;++i)
    {
        cin>>a[i];
        dp[i][i]=a[i];  ///i-i区间
        pre[i][i]=i;
    }
    for(int len=2;len<=n;++len)///区间长度
    {
        for(int i=1;i+len-1<=n;++i)///起始点
        {
            int j=i+len-1;///终点
            dp[i][j]=0;
            for(int k=i;k<=j;++k)
            {
                ll v=dp[i][k-1]*dp[k+1][j]+a[k];///遍历求最大
                if(dp[i][j]<v)
                {
                    dp[i][j]=v;
                    pre[i][j]=k;///记录i-j区间的根节点
                }
            }
        }
    }
    cout<<dp[1][n]<<endl;
    dfs(1,n);///根据前序遍历的特点输出
    return 0;
}