zoukankan      html  css  js  c++  java
  • [NOIP2003]加分二叉树

    嘟嘟嘟

    中序遍历有一个特点:序列[1, n]是一个中序遍历,i 是根节点,则[1, i - 1]是他的左子树的中序遍历,[i + 1, n]为右子树的中序遍历。所以就想到了区间dp,对于[i, j]枚举根节点k,则dp[i][j] = max(dp[i][k - 1] * dp[k + 1][j] + a[k])。初始化dp[i][i] = a[i],又因为空节点为1,所以dp[i][i - 1] = 1。

    前序遍历的话就再开一个二维数组f[i][j]存这个区间所属哪一个节点,输出的时候跟区间dp很像,具体看代码吧。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const int maxn = 35;
    21 inline ll read()
    22 {
    23   ll ans = 0;
    24   char ch = getchar(), last = ' ';
    25   while(!isdigit(ch)) {last = ch; ch = getchar();}
    26   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    27   if(last == '-') ans = -ans;
    28   return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32   if(x < 0) x = -x, putchar('-');
    33   if(x >= 10) write(x / 10);
    34   putchar(x % 10 + '0');
    35 }
    36 
    37 int n, a[maxn];
    38 ll dp[maxn][maxn];
    39 int f[maxn][maxn];
    40 
    41 void print(int L, int R)
    42 {
    43   if(R < L) return;
    44   if(L == R) {write(L), space; return;}
    45   write(f[L][R]), space;
    46   print(L, f[L][R] - 1);
    47   print(f[L][R] + 1, R);
    48 }
    49 
    50 int main()
    51 {
    52   n = read();
    53   for(int i = 1; i <= n; ++i) a[i] = read();
    54   for(int i = 1; i <= n; ++i) dp[i][i] = a[i], dp[i][i - 1] = 1;
    55   for(int L = 2; L <= n; ++L)
    56     for(int i = 1; i + L - 1 <= n; ++i)
    57       {
    58     int j = i + L - 1;
    59     for(int k = i; k <= j; ++k)
    60       {
    61         ll Max = dp[i][k - 1] * dp[k + 1][j] + a[k];
    62         if(Max > dp[i][j]) dp[i][j] = Max, f[i][j] = k;
    63       }
    64       }
    65   write(dp[1][n]); enter;
    66   print(1, n);
    67   return 0;
    68 }
    View Code
  • 相关阅读:
    Dragon(preview)
    Release My New Single Album: Open The Door
    Writing REYES
    Expecting New Design: MiniMemMan
    never use virtual function for primitives!
    far.md
    ACL使用.md
    什么是技术,技术是什么
    Js客户端判断上传文件的类型
    color table
  • 原文地址:https://www.cnblogs.com/mrclr/p/9809207.html
Copyright © 2011-2022 走看看