加分二叉树

#include <bits/stdc++.h>
using namespace std;
//加分二叉树
int n,dp[40][40]={0},a[40],ans=0,root[40][40];
void f(int i,int j){
    if(i>j) return;
    cout<<root[i][j]<<" ";
    f(i,root[i][j]-1);
    f(root[i][j]+1,j);
}
int main() {
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int l=1;l<=n;l++){
        for(int i=1;i<=n-l+1;i++){
            int j=l+i-1;
            //k有区间的根节点的位置
            //事实上,在已有两个点时,怎么左右子树哪一个是空没有区别,答案优先左子树是空
            //这么写是因为,在左右子树是空的时候,会有一个dp[i][k-1]、dp[k+1][j]=0,会干扰
            if(dp[i+1][j]+a[i]>=dp[i][j-1]+a[j]){
                //只有两个点时,dp[i+1][j]+a[i]=dp[i][j-1]+a[j],这是规定选择i为根
                dp[i][j]=dp[i+1][j]+a[i];
                root[i][j]=i;
            } else{
                dp[i][j]=dp[i][j-1]+a[j];
                root[i][j]=j;
            }
            //左右都不是空
            for(int k=i;k<=j;k++){
                if(dp[i][k-1]*dp[k+1][j]+a[k]>dp[i][j]){
                    dp[i][j]=dp[i][k-1]*dp[k+1][j]+a[k];
                    root[i][j]=k;
                }
            }
            ans=max(ans,dp[i][j]);
        }
    }
    cout<<ans<<endl;
    f(1,n);
    return 0;
}

 

posted @ 2020-06-06 21:11  西伯利亚挖土豆  阅读(149)  评论(0编辑  收藏  举报