题目链接:https://www.acwing.com/problem/content/481/
思路:因为在中序遍历中,每一棵子树在序列中是连续的一段
所以可以考虑区间dp来计算1~n的合并顺序 dp[i][j] 代表从i~j的一棵二叉树的最大值
然后以根节点k来作为划分子集的依据 每次可以用左子树×右子树 来更新 记得特判边界的问题
因为要输出方案 所以 用g[i][j] 代表i~j这一段的根节点是谁 然后先序递归的时候 输出根节点即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e2+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define ull unsigned long long 7 #define pi pair<int,int> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 12 int dp[maxn][maxn]; 13 int w[maxn]; 14 int g[maxn][maxn]; 15 16 17 void dfs(int l,int r) 18 { 19 int rt=g[l][r]; 20 cout<<rt<<" "; 21 if(l<rt) dfs(l,rt-1); 22 if(r>rt) dfs(rt+1,r); 23 } 24 25 26 int main() 27 { 28 ios::sync_with_stdio(false); 29 cin.tie(0); 30 int n; 31 cin>>n; 32 for(int i=1;i<=n;i++) cin>>w[i]; 33 for(int len=1;len<=n;len++) 34 { 35 for(int i=1;i+len-1<=n;i++) 36 { 37 int j=i+len-1; 38 if(len==1) dp[i][j]=w[i],g[i][j]=i; 39 else 40 { 41 for(int k=i;k<=j;k++) 42 { 43 int l=k==i?1:dp[i][k-1]; 44 int r=k==j?1:dp[k+1][j]; 45 46 int tmp=l*r+w[k]; 47 if(tmp>dp[i][j]) 48 { 49 dp[i][j]=tmp; 50 g[i][j]=k; 51 } 52 } 53 } 54 } 55 } 56 cout<<dp[1][n]<<‘\n‘; 57 dfs(1,n); 58 59 60 61 62 63 64 65 }
原文:https://www.cnblogs.com/winfor/p/14670949.html