码迷,mamicode.com
首页 > 其他好文 > 详细

P1040 加分二叉树

时间:2019-07-16 14:05:29      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:==   ++   names   string   一个   ret   new   org   i+1   

题面:https://www.luogu.org/problemnew/show/P1040

本题即一个在树上做的区间dp,只不过中间枚举的断点k即为当前dp到的树的根节点,然后将当前区间分为两段,即为树上的左子树和右子树,不过要注意这里的k可以取到端点值,即k的取值范围为[i,j]因为一棵树的左右子树可以为空,接着用dp方程f[i][j]=max(f[i][j],f[i][k-1]*f[k+1][j]+f[k][k])就能求解,那么前序遍历也就自然很好解决了。

Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
const int N=35;
int n,front[N][N];
long long f[N][N];
void printf_front(int l,int r){
    if(l>r){
        return;
    }
    printf("%d ",front[l][r]);
    if(l==r){
        return;
    }
    printf_front(l, front[l][r]-1);
    printf_front(front[l][r]+1,r);
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld", &f[i][i]);
        f[i][i-1]=1;
        f[i][i+1]=1;
        front[i][i]=i;
    }
    for(int len=1;len<n;len++){
        for(int i=1;i+len<=n;i++){
            int j=i+len;
            for(int k=i;k<=j;k++){
                if(f[i][j]<f[i][k-1]*f[k+1][j]+f[k][k]){
                    f[i][j]=f[i][k-1]*f[k+1][j]+f[k][k];
                    front[i][j]=k;
                }
            }
        }
    }
    printf("%lld\n",f[1][n]);
    printf_front(1,n);
    return 0;
}

P1040 加分二叉树

标签:==   ++   names   string   一个   ret   new   org   i+1   

原文地址:https://www.cnblogs.com/ukcxrtjr/p/11194425.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!