[NOIP2003]区间dp-加分二叉树

来源:互联网 发布:天财商龙餐饮软件下载 编辑:程序博客网 时间:2024/05/28 11:48

题目描述见luogu
https://www.luogu.org/problem/show?pid=1040

是很明显的区间dp 我企图用平行四边形优化 未遂
因为我区间dp不是很熟 所以把这道题摆上来
是一道很好的模板题 其中用d[i][j]记录切点也给二叉树的遍历提供了不错的例子
需要注意的点都在代码里注释了
f[i][j]=f[i][k-1]*f[k+1][j]+a[k]

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,a[50];long long f[50][50];  int d[50][50];void print(int i,int j){    if(i>j)return ;    int k=d[i][j];      //前序遍历 根左右    printf("%d ",k);    print(i,k-1);    print(k+1,j);    return ;}int main(){    cin>>n;    for(int i=1;i<=n;++i){        cin>>a[i];        f[i][i]=a[i];   //当i为叶子时,加分为它的权重        d[i][i]=i;    }    //第一层l 第二层i  第三层k  真玄学啊    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 x=f[i][k-1];  //注意是f[i][k-1]不是f[i][k]                if(!x)x=1;                long long y=f[k+1][j];                if(!y)y=1;                if(f[i][j]<x*y+a[k]){                    f[i][j]=x*y+a[k];                    d[i][j]=k;//记录切点                }            }        }    }    cout<<f[1][n]<<endl;    print(1,n);    //while(1);    return 0;}
原创粉丝点击