题目
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
int a[N];
int f[N][N], root[N][N];
int n;
void Print(int i, int j)
{
if(i == j)
{
cout << i << " ";
return;
}
if(i > j) return;
int k = root[i][j];
cout << k << " ";
Print(i, k-1);
Print(k+1, j);
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i], f[i][i] = a[i];
for(int len = 2; len <= n; len++)
{
for(int i = 1, j; (j = i + len - 1) <= n; i++)
{
for(int k = i; k <= j; k++)
{
if(k == i)
{
if(f[i][j] < a[k] + f[k+1][j])
f[i][j] = a[k] + f[k+1][j], root[i][j] = k;
}
else if(k == j)
{
if(f[i][j] < a[k] + f[i][k-1])
f[i][j] = a[k] + f[i][k-1], root[i][j] = k;
}
else
{
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], root[i][j] = k;
}
}
}
}
cout << f[1][n] << endl;
Print(1, n);
return 0;
}
思路
我们知道中序遍历中,根节点将左子树节点和右子树节点分开。在前序遍历中,某棵树的节点序列中的第一个节点是根节点
状态定义
为题给中序遍历中从第 个 节点开始,到第 个节点结束,各自包含,所形成一棵树方法集合
的值代表方法集合中的加分最大值
状态转移
我们枚举可能的根节点 ,将左子树和右子树合成一棵树
对于 的情况,
对于 的情况,左子树不存在,
对于 ,右子树不存在,
目标状态
前序遍历
在每次 被更新的情况下,同时更新对应树的根节点。最后编写一个递归函数,根据根节点集合按照根、左、右的顺序输出,也就是先输出根,再按照左、右顺序套娃