zoukankan      html  css  js  c++  java
  • 加分二叉树(递归,区间DP)

    算法
    (区间DP,二叉树的遍历)

    状态表示:(f[i][j]) 表示中序遍历是 (w[i~j]) 的所有二叉树的得分的最大值。

    状态计算:(f[i][j] = max(f[i][k - 1] * f[k + 1][j] + w[k])),即将(f[i][j])表示

    的二叉树集合按根节点分类,则根节点在 k 时的最大得分即

    (f[i][k - 1] * f[k + 1][j] + w[k])(f[i][j])即为遍历 k 所取到的最大值。

    在计算每个状态的过程中,记录每个区间的最大值所对应的根节点编号。

    那么最后就可以通过DFS求出最大加分二叉树的前序遍历了。

    时间复杂度状态总数是 (O(n^2)),计算每个状态需要 (O(n))的计算量,因此总时间复杂度是(O(n^3))

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef pair<int, int> PII;
    
    const int N = 50;
    
    int n;
    int w[N];
    unsigned f[N][N];
    int root[N][N];
    
    void dfs(int l, int r)
    {
        if (l > r) return;
    
        int k = root[l][r];
        printf("%d ", k);
        dfs(l, k - 1);
        dfs(k + 1, r);
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
        for (int len = 1; len <= n; len ++ )
            for (int l = 1; l + len - 1 <= n; l ++ )
            {
                int r = l + len - 1;
    
                for (int k = l; k <= r; k ++ )
                {
                    int left = k == l ? 1 : f[l][k - 1];
                    int right = k == r ? 1 : f[k + 1][r];
                    int score = left * right + w[k];
                    if (l == r) score = w[k];
                    if (f[l][r] < score)
                    {
                        f[l][r] = score;
                        root[l][r] = k;
                    }
                }
            }
    
        printf("%d
    ", f[1][n]);
        dfs(1, n);
        puts("");
    
        return 0;
    }
    
  • 相关阅读:
    phpmyadmin漏洞复现
    ecshop漏洞复现
    php漏洞复现
    discuz漏洞复现
    gitlab漏洞复现
    Elasticsearch漏洞复现
    flask漏洞复现
    Hikari配置
    DOM&BOM的起源,方法,内容,应用
    vue 实现div方框内大图自由拖拽
  • 原文地址:https://www.cnblogs.com/bangdexuanyuan/p/13798916.html
Copyright © 2011-2022 走看看