唉 天天摸鱼导致一感冒 好点后再写题解都超时了
虽然没牛币可以白嫖但还是写写自己的理解吧
这题我们要抓住中序遍历的特点 以根节点划分左子树右子树
这样就可以不断递归下去求
解法就出来了 区间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;
}

京公网安备 11010502036488号