解题思路:
- 问题分析为对于一个中序输入的树,根据规则找出组合积分最大值,即是以输入vi做为root,枚举每一个root构成的树形所得到的最大积分。
- 对于每一个构成这棵树的子树也同样符合规则,从节点数2→n进行枚举每一个组合选出最大组合积分。令dpl,r表示从编号l到编号r的最大积分值,则很容易得到状态转移方程:dpl,r=max(dpl,r,dpl,root−1+dproot+1,r+vroot)
- 同时可以记录每个<l,r>区间中的产生最大值的root,最后递归输出即可。
#include<bits/stdc++.h>
using namespace std;
void print_root(int l, int r, vector<vector<int>> &record){
if (l > r) return;
cout<< record[l][r]+1<<" ";
print_root(l, record[l][r] - 1 , record);
print_root(record[l][r] + 1, r, record);
}
int main(){
int n;
cin >>n;
vector<int> v(n);
vector<vector<int>> dp(n,vector<int> (n));
vector<vector<int>> record(n, vector<int>(n));
for(int i = 0; i < n; ++i){
cin>> v[i];
dp[i][i] = v[i];//对于单节点区间中的积分值就是其自己
record[i][i] = i;//对于单节点区间中的root亦是其自己
}
for(int len = 2; len <= n; ++len){
int mx_l, mx_r,mx_root;
for(int l = 0; l < n; ++l){
int r = l + len - 1;
if(r >= n) break;
for(int root = l; root <= r; ++root){
int tmp = (root-1 < l ? 1: dp[l][root-1]) * (root+1 > r? 1: dp[root+1][r]) + v[root];
if(tmp > dp[l][r]) {
dp[l][r] = tmp;
record[l][r] = root;
}
}
}
}
cout<<dp[0][n-1]<<endl;
print_root(0,n-1,record);
return 0;
}