【NOIP2003提高组】加分二叉树

https://www.luogu.org/problem/show?pid=1040

令f(i,j)表示[i,j]的二叉树中最高的分数。
枚举k为根,状转方程:f(i,j)=max{f(i,k-1)*f(k+1,j)+num[k]} (i<=k<=j)
做决策的时候保存最优解的根,然后模拟前序遍历递归打印。

#include <iostream>
using namespace std;
int n, num[40], root[40][40];
unsigned long long dp[40][40];
void print(int i, int j)
{
    if (i == j)
        cout << i << ' ';
    else if (i < j)
    {
        cout << root[i][j] << ' ';
        print(i, root[i][j] - 1);
        print(root[i][j] + 1, j);
    }
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> num[i];
    // f(i,j)=max{f(i,k-1)*f(k+1,j)+num[k]} (i<=k<=j)
    for (int i = 1; i <= n; i++)
        dp[i][i] = num[i];
    for (int len = 2; len <= n; len++)
    {
        for (int i = 1, j = len; j <= n; i++, j++)
        {
            for (int k = i; k <= j; k++)
            {
                int multiple = 1;
                if (k != i)
                    multiple *= dp[i][k - 1];
                if (k != j)
                    multiple *= dp[k + 1][j];
                if (dp[i][j] < num[k] + multiple)
                {
                    dp[i][j] = num[k] + multiple;
                    root[i][j] = k;
                }
            }
        }
    }
    cout << dp[1][n] << endl;
    print(1, n);
    return 0;
}
原文地址:https://www.cnblogs.com/ssttkkl/p/7078430.html