【Luogu】P1040加分二叉树(区间DP)

  题目链接

  区间DP,因为中序遍历的性质:区间[l,r]的任何一个数都可以是该区间的根节点。

  更新权值的时候记录区间的根节点,最后DFS输出。

  见代码。

  

#include<cstdio>
#include<cctype>
#include<algorithm>
inline long long max(long long a,long long b){    return a>b?a:b;    }
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long f[500][500];
int rt[500][500];
int que[500];

void dfs(int x,int y){
    printf("%d ",rt[x][y]);
    if(rt[x][y]>x)    dfs(x,rt[x][y]-1);
    if(rt[x][y]<y)    dfs(rt[x][y]+1,y);
}

int main(){
    int n=read();
    for(int i=1;i<=n;++i){
        f[i][i]=que[i]=read();
        rt[i][i]=i;
    }
    
    for(int l=2;l<=n;++l)
        for(int i=1;i+l-1<=n;++i){
            int j=i+l-1;
            for(int k=i;k<=j;++k){
                long long L=f[i][k-1],R=f[k+1][j];
                if(k==i&&k!=j)    L=1;
                if(k==j&&k!=i)    R=1;
                if(f[i][j]<L*R+f[k][k]){
                    rt[i][j]=k;
                    f[i][j]=L*R+f[k][k];
                }
            }
        }
    printf("%lld\n",f[1][n]);
    dfs(1,n);
    return 0;
}

 

posted @ 2017-09-26 07:22  Konoset  阅读(175)  评论(0编辑  收藏  举报