洛谷P1040加分二叉树-题解
题目:
思路:
这题在一个细节上很奇怪,它给树是按中序遍历给的
而且只给了中序遍历
这意味着我们可以通过自己的方式来构造这棵树
我们回想一下——
在中序遍历中,一个根节点的左儿子是?
——这个节点的左边所有
右儿子是?
——右半部分
如果用区间表示呢?
——[i.k-1],[k+1,j]
为什么没有k?
——根节点不在左右儿子之列
我们一回来看这道题,发现区间DP简直是专门设计出来解决这类题的
枚举k,利用左右区间值计算大区间值
基本就是区间DP用惯了的套路
至于输出遍历
只要在DP时记下这个区间的根,然后递归即可
代码:
#include <bits/stdc++.h> using namespace std; long long n; long long f[50][50], root[50][50]; void print(long long l, long long r) { if (l > r) return; cout << root[l][r] << ' '; if (l == r) return; print(l, root[l][r] - 1); print(root[l][r] + 1, r); } int main() { cin >> n; for (int i = 1; i <= n; i++) { cin >> f[i][i]; f[i][i - 1] = 1; root[i][i] = i; } for (int len = 1; len <= n; len++) { for (int i = 1; i + len <= n; i++) { int j = i + len; f[i][j] = f[i][i] + f[i + 1][j]; root[i][j] = i; for (int k = i + 1; k < j; k++) { if (f[i][j] < f[i][k - 1] * f[k + 1][j] + f[k][k]) { f[i][j] = f[i][k - 1] * f[k + 1][j] + f[k][k]; root[i][j] = k; } } } } cout << f[1][n] << endl; print(1, n); return 0; }