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

加分二叉树

时间:2019-11-24 13:43:37      阅读:55      评论:0      收藏:0      [点我收藏+]

标签:sam   return   namespace   scan   desc   pre   前序遍历   include   std   

加分二叉树

Description

设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数 若某个子树为空,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空子树。

试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出:

(1)tree的最高加分

(2)tree的前序遍历

Input

第1行:一个整数n(n<30)为节点个数。 第2行:n个用空格隔开的整数,为每个节点的分数(分数<100)。

Output

第1行:一个整数,为最高加分(结果不会超过4,000,000,000)。 第2行:n个用空格隔开的整数,为该树的前序遍历。

Sample Input

5
5 7 1 2 10

Sample Output

145 
3 1 2 4 5

HINT

Source

#include <bits/stdc++.h>
using namespace std;
int n, a[101];
int opt[101][101];
int f[101][101];
int solve (int p, int q) {
    if (f[p][q] != -1) {
        return f[p][q];
    }
    if (p > q) {
        f[p][q] = 1;
        return 1;
    }
    else if (p == q) {
        opt[p][p] = p;
        f[p][q] = a[p];
        return f[p][q];
    }
    int ans = 0;
    for (int r = p; r <= q; r ++) {
        int res = solve(p, r - 1) * solve(r + 1, q) + a[r];
        if (res > ans) {
            ans = res;
            opt[p][q] = r;
        }
    }
    f[p][q] = ans;
    return f[p][q];
}
void proot(int p, int q) {
    if (p > q) {
        return ;
    }
    printf("%d ", opt[p][q]);
    proot(p, opt[p][q] - 1);
    proot(opt[p][q] + 1, q);
}
int main() {
    cin >> n;
    memset(f, -1, sizeof(f));
    for (int i = 1; i <= n; i ++) {
        scanf("%d", &a[i]);
    }
    cout << solve(1, n) << endl;
    proot(1, n);
    return 0;
}

递归写法

#include <bits/stdc++.h>
using namespace std;
int n, a[101];
int opt[101][101];
int f[101][101];
void print(int p, int q) {
    if (p > q) return ;
    printf ("%d ", opt[p][q]);
    print(p, opt[p][q] - 1);
    print(opt[p][q] + 1, q);
}
int main() {
    cin >> n;
    memset(f, -1, sizeof(f));
    for (int i = 1; i <= n; i ++) {
        scanf("%d", &a[i]);
        f[i][i] = a[i];
        f[i][i - 1] = 1;
        opt[i][i] = i;
    }
    for (int len = 2; len <= n; len ++) {
        for (int i = 1; i <= n; i ++) {
            int j = i + len - 1;
            for (int k = i; k <= j; k ++) {
                if (f[i][j] < f[i][k - 1] * f[k + 1][j] + a[k]) {
                    f[i][j] = f[i][k - 1] * f[k + 1][j] + a[k];
                    opt[i][j] = k;
                }
            }
        }
    }
    cout << f[1][n] << endl;
    print(1, n);
    return 0;
}

加分二叉树

标签:sam   return   namespace   scan   desc   pre   前序遍历   include   std   

原文地址:https://www.cnblogs.com/LJA001162/p/11922071.html

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