zoukankan      html  css  js  c++  java
  • [洛谷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/),未经允许,不得转载。
  • 相关阅读:
    IAccessible ( 一 )
    object sender,EventArgs e的一些讲解
    C# 操作符重载
    MSAA简介
    小试NArrange
    C++宏
    Ext.form.ComboBox简单用法
    SQL SERVER 收缩数据库的命令
    ext.grid的配置属性和方法
    磁盘阵列
  • 原文地址:https://www.cnblogs.com/juruoajh/p/12520196.html
Copyright © 2011-2022 走看看