原来以为是树上DP,后来发现中序遍历的连续性,就变成区间动规了
f[i][j]表示从i到j能取得的分数最大值,rt[i][j]表示取得最大值是该段区间的根
#include<cstdio> #include<cctype> using namespace std; int n,a[30],rt[30][30]; long long f[30][30]; inline void read(int &x){ char ch=getchar();x=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} } inline void putans(int l,int r){ if(l>r||l<1||r>n)return; printf("%d ",rt[l][r]); putans(l,rt[l][r]-1);putans(rt[l][r]+1,r); } int main(){ read(n);for(int i=1;i<=n;i++){read(a[i]);f[i][i]=a[i];f[i][i-1]=1;rt[i][i]=i;}f[n+1][n]=1; for(int i=1;i<n;i++) for(int j=1;j<=n-i;j++) for(int k=j;k<=j+i;k++){ int now=f[j][k-1]*f[k+1][j+i]+a[k]; if(now>f[j][j+i]){f[j][j+i]=now;rt[j][j+i]=k;} } printf("%d\n",f[1][n]); putans(1,n); }