二叉树??树状dp??NONONO!!!
本题的树不固定,他要求去找出来一个最优的树,所以不适合使用树状dp去进行求解。但又因为题中所给的有中序遍历的序列,中序遍历序列最大的特点在于定根可将区间分成左右子树。
那么分成两部分之后就可以分别去计算这两部分,也就是在这两小部分里面取找根。
那么可以得到dp[i][j]为i,j这个区间组成的树的最高加分。
得到状态转移方程为:dp[i][j] = max(dp[i][k], dp[k+1][j])。
对于前序遍历:在每一个区间树遍历最高加分的时候去记录最优的那个根。然后重新dfs遍历得到就行。
那么可以得到dp[i][j]为i,j这个区间组成的树的最高加分。
得到状态转移方程为:dp[i][j] = max(dp[i][k], dp[k+1][j])。
对于前序遍历:在每一个区间树遍历最高加分的时候去记录最优的那个根。然后重新dfs遍历得到就行。
//题目中所给的是一个中序遍历的序列,那么只要定下一个根就可以将这个序列分成左右两部分。 //分成两部分之后就可以分别去计算这两部分,也就是在这两小部分里面取找根。 //那么可以得到dp[i][j]为i,j这个区间组成的树的最高加分。 //得到状态转移方程为:dp[i][j] = max(dp[i][k], dp[k+1][j])。 //对于前序遍历:在每一个区间树遍历最高加分的时候去记录最优的那个根。然后重新dfs遍历得到就行。 #include <bits/stdc++.h> using namespace std; const int maxn = 33; int n; int a[maxn]; int dp[maxn][maxn]; int zhong[maxn][maxn]; void dfs(int l, int r) { if (l==r) { cout<<l<<' '; return ; } if (l>r) return ; int mid = zhong[l][r]; int l1 = l; int r1 = mid-1; int l2 = mid+1; int r2 = r; cout<<mid<<" "; dfs(l1, r1);dfs(l2, r2); } int main() { cin>>n; for (int i=1;i<=n;i++) cin>>a[i]; for (int len = 1;len<=n;len++) { for (int l = 1;l<=n-len+1;l++) { int r = l+len-1; if (len==1) dp[l][r] = a[l]; else{ for (int k=l;k<=r;k++) { int num = (l<=k-1? dp[l][k-1]:1) * (k+1<=r? dp[k+1][r]:1) + dp[k][k]; if (dp[l][r]<num) { dp[l][r] = num; zhong[l][r] = k; } } } } } cout<<dp[1][n]<<endl; //通过之前记录的来进行dfs输出前序遍历 dfs(1, n); return 0; }