加分二叉树

加分二叉树

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 
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 
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;
}

你可能感兴趣的:(加分二叉树)