题目:
一棵二叉树的中序遍历是1、2、3...n。每个结点有点权a[i]。让你确定一棵树使val最大。最后输出val并给出先序遍历序列。
(n最大100)
做法:
一个区间DP的题。但感觉dfs码起来更清晰,思路是一样的。
对[l,r]区间确定的一棵二叉树,它的我们通过枚举根节点的位置来转移: 转移时记录此区间的根,回头打印先序遍历时就很简单了。
具体细节看代码咯。
代码:
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false), cin.tie(0) #define debug(a) cout << #a ": " << a << endl using namespace std; typedef long long ll; const int N = 110; int n, a[N], dp[N][N], path[N][N]; int dfs(int l, int r){ if (dp[l][r] != -1) return dp[l][r]; if (l == r){ path[l][r] = l; return a[l]; } if (l > r) return 1; int& ans = dp[l][r] = 0; for (int i = l; i <= r; ++i){ int tmp = dfs(l, i-1)*dfs(i+1, r)+a[i]; if (ans < tmp){ ans = tmp; path[l][r] = i; } } return ans; } void getpath(int l, int r){ if (l > r) return; cout << path[l][r] << ' '; getpath(l, path[l][r]-1); getpath(path[l][r]+1, r); } int main(void){ IOS; int n; cin >> n; for (int i = 1; i <= n; ++i) cin >> a[i]; memset(dp, -1, sizeof dp); cout << dfs(1, n) << endl; getpath(1, n); return 0; }