0.总结
Get to the points first. The article comes from LawsonAbs!- 区间dp
- 转换思路
- 二叉树的遍历
1.题意
2.主要思路
- 区间dp
区间dp的套路是固定的。可以参考我之前写的博客区间DP 。相较区间dp而言,我觉得本题的重点是:为什么可以用区间dp解决此题? 因为给出的二叉树遍历是中序序列,所以可以采用区间DP【因为任意一段序列在树中必是连续的】,但如果是先序或者后序遍历,则区间dp不一定能顺利解决。 - 思路转换
本题的坑点是:切莫以为要先确定树长什么样子才能解决此题,然后就掉进“先求树,再计算值”的冗余复杂过程里。
3.代码
#include<iostream>
using namespace std;
const int N = 35;
int score[N];
int dp[N][N],root[N][N];
void pre(int left,int right){
int r = root[left][right];
if(left > right){
r = left;
return ;
}
cout << r <<" ";
pre(left,r-1);
pre(r+1,right);
}
int main(){
int n;
cin >> n;
for(int i = 1;i<=n;i++){
cin >> score[i];
dp[1][i] = score[i];
root[i][i] = i;
}
int temp ,left,right;
for(int len = 2;len <=n ;len++){
for(int i = 1;i <= n-len + 1;i++){
int j = i+len-1;
for(int k = i;k<=j;k++) {
if(k==i)
left = 1;
else
left = dp[k-i][i];
if(k == j)
right = 1;
else
right = dp[j-k][k+1];
temp = left * right + score[k];
if(temp > dp[len][i]){
dp[len][i] = temp;
root[i][j] = k;
}
}
}
}
cout << dp[n][1]<<"\n";
pre(1,n);
}