• [洛谷P1040][题解]加分二叉树


    题目戳我!

    这个题的难度是绿色,众所周知青菜是绿色的,所以这题一定很菜,实际上确实是(你不还是看了题解)

    我们可以设计出这样一个状态:f[l][r]代表从l到r的最高加分,结果就是f[1][n]

    怎样转移?

    一棵子树肯定要有根,所以我们就枚举根!

    在一段区间[i,j]里,揪出来一个根k,然后转移:f[l][r]=max(f[l][k-1]*f[k+1][r]+f[k][k])

    其中f[k][k]显然就是自身的权值了

    因为揪出根之后剩下的区间一定比之前小,所以要按长度从小往大枚举区间

    输出的话记录一下i到j这棵子树揪出来的根就好啦~

    Code:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<ctime>
     5 #include<cstring>
     6 #include<iostream>
     7 #include<algorithm>
     8 #include<stack>
     9 #include<queue>
    10 #include<vector>
    11 #include<bitset>
    12 #include<set>
    13 #include<map>
    14 #define LL long long
    15 #define rg register
    16 #define us unsigned
    17 #define eps 1e-6
    18 #define INF 0x3f3f3f3f
    19 #define ls k<<1
    20 #define rs k<<1|1
    21 #define tmid ((tr[k].l+tr[k].r)>>1)
    22 #define nmid ((l+r)>>1)
    23 #define Thispoint tr[k].l==tr[k].r
    24 #define pushup tr[k].wei=tr[ls].wei+tr[rs].wei
    25 #define pub push_back
    26 #define lth length
    27 #define int long long
    28 using namespace std;
    29 inline void Read(int &x){
    30     int f=1;
    31     char c=getchar();
    32     x=0;
    33     while(c<'0'||c>'9'){
    34         if(c=='-')f=-1;
    35         c=getchar();
    36     }
    37     while(c>='0'&&c<='9'){
    38         x=(x<<3)+(x<<1)+c-'0';
    39         c=getchar();
    40     }
    41     x*=f;
    42 }
    43 #define N 40
    44 int n,f[N][N],pr[N][N];
    45 inline void Initi(){
    46     Read(n);
    47     for(rg int i=1;i<=n;i++){
    48         Read(f[i][i]);
    49         pr[i][i]=i;
    50     }
    51 }
    52 inline void Solve(){
    53     for(rg int len=1;len<n;len++){
    54         for(rg int l=1;l+len<=n;l++){
    55             int r=l+len;
    56             //初始情况
    57             //加分:没有左子树一定最小 
    58             //根:先记上左端点 
    59             f[l][r]=f[l+1][r]+f[l][l],pr[l][r]=l;
    60             for(rg int k=l+1;k<r;k++){
    61                 if(f[l][r]<f[l][k-1]*f[k+1][r]+f[k][k]){
    62                     f[l][r]=f[l][k-1]*f[k+1][r]+f[k][k];
    63                     pr[l][r]=k;//转移+记录 
    64                 }
    65             }
    66         }
    67     }
    68 }
    69 inline void Print(int l,int r){
    70     if(l>r)return;
    71     printf("%lld ",pr[l][r]);
    72     if(l!=r){
    73         Print(l,pr[l][r]-1);
    74         Print(pr[l][r]+1,r);
    75     }else return;
    76 }
    77 signed main(){
    78     Initi();
    79     Solve();
    80     printf("%lld
    ",f[1][n]);
    81     Print(1,n);
    82     return 0;    
    83 }
    内容来自_ajhfff_的博客(https://www.cnblogs.com/juruoajh/),未经允许,不得转载。
  • 相关阅读:
    Hbase shell基本操作
    Spring Caching集成Ehcache
    统一认证授权及单点登录的技术选择
    详谈再论JAVA获取本机IP地址
    Spark基础脚本入门实践3:Pair RDD开发
    Spark基础脚本入门实践2:基础开发
    Spark基础脚本入门实践1
    必须熟练的基础linux命令
    Swing中的线程并发处理
    源码分享!!!world文档转换为JPG图片
  • 原文地址:https://www.cnblogs.com/juruoajh/p/12520196.html
Copyright © 2020-2023  润新知