很明显的一道区间dp题目。
和acwing上的金字塔有点像。
表面上感觉是树形dp,实则不然。
题中给出的1~n是中序遍历,
按照区间dp的套路
设f[l][r]为中序遍历是l~r的子树的最大加分值。
那么划分点佷显然就是枚举一颗子树的根节点,再加上这棵树是一颗二叉树就更好办了。
dp方程如下
for(int len=2;len<=n;len++)
for(int l=1;l<=n-len+1;l++){
int r=l+len-1;
for(int k=l;k<=r;k++){
f[l][r]=max(f[l][r],f[l][k-1]*f[k+1][r]+a[k]);
}
}
#include<bits/stdc++.h>
using namespace std;
int n,root;
int a[33];
int f[33][33];
struct node{
int l,r;
}t[33];
int dfs(int l,int r){
if(l==r) return l;
if(l>r) return 0;
for(int i=l;i<=r;i++)
if(f[l][r]==f[l][i-1]*f[i+1][r]+a[i]){
t[i].l=dfs(l,i-1);
t[i].r=dfs(i+1,r);
return i;
}
}
vector<int> v;
void qian(int x){
if(x==0) return ;
v.push_back(x);
qian(t[x].l);
qian(t[x].r);
return ;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
f[i][i]=a[i];
}
for(int i=1;i<=n;i++)
f[i+1][i]=f[i][i-1]=1;
for(int len=2;len<=n;len++)
for(int l=1;l<=n-len+1;l++){
int r=l+len-1;
for(int k=l;k<=r;k++){
f[l][r]=max(f[l][r],f[l][k-1]*f[k+1][r]+a[k]);
}
}
root=dfs(1,n);
qian(root);
cout<<f[1][n]<<endl;
for(int i=0;i<v.size();i++)
cout<<v[i]<<" ";
return 0;
}