Interval DP: Bonus Binary Tree

Design an in-order traversal of a binary tree. Nodes are numbers (1 , 2 , 3 , … , n), where the number 1 , 2 , 3 , … , n is the node id. Each node has a score (positive integer) and each subtree has a bonus. The subtree bonus calculation is based on bonus of its subtrees and the score of the node itself:       bonus for the left subtree * bonus for the right subtree + the score of the root of the subtree 

If a subtree is empty, then the bonus is 1, all the leaf nodes’ bonus is the score of the leaf node.

Try to find a tree that gives an in-order traversal as (1 , 2 , 3 , … , n) and the binary tree with the highest bonus.

Request output: 

(1) The highest points for tree  (2) Preorder traversal of tree

Input format First row: an integer n, Is the number of nodes.  Second row: an integer separated by a space is the score of each node (0 <fraction< 100).

Output format First row: an integer, which is the highest bonus point (the result will not exceed the intrange).      Second row: an integer separated by a space which is the print out of pre-order traversal of the tree. If there are multiple schemes, the scheme with the smallest lexicographic order is output.

data range n < 30

Sample Input:

5
5 7 1 2 10

Sample Output:

145
3 1 2 4 5

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#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 dp[N][N];
int root[N][N];

//print out the in-order traversal of the binary tree
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]);

    //out loop: length of the binary tree range
    for (int len = 1; len <= n; len ++ )
        //inner loop: left index of the binary tree
        for (int l = 1; l + len - 1 <= n; l ++ )
        {
            //right index
            int r = l + len - 1;

            // try different possible root of the binary tree
            for (int k = l; k <= r; k ++ )
            {
                int left = k == l ? 1 : dp[l][k - 1];
                int right = k == r ? 1 : dp[k + 1][r];

                int score = left * right + w[k];

                if (l == r) score = w[k];

                if (dp[l][r] < score)
                {
                    dp[l][r] = score;
                    root[l][r] = k;
                }
            }
        }

    printf("%d\n", dp[1][n]);
    dfs(1, n);
    puts("");

    return 0;
}