原解法: 548 - Tree
改进: 不建树, 而是在建树的过程中把根节点到各个叶节点的和都算出来, 因为建树的时候就是一个由顶到下的过程, 所以是可以把这段路径上的和给算出来的; 使用一个全局 pair 存放最小的和, 每算出一个和, 就与全局的 pair 相比, 若比当前小, 则替换当前全局 pair, 最后再输出这个 pair 的叶子节点值即可.
要点:
1. numeric_limits<int>::max(); // <limits> 获取 int 最大值.
题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=104&page=show_problem&problem=489
代码:
# include <iostream> # include <string> # include <cstdio> # include <cstring> # include <vector> # include <algorithm> # include <cctype> # include <iterator> # include <sstream> # include <assert.h> # include <limits> using namespace std; // 不建树, 而是在建树的过程中把根节点到各个叶节点的和都算出来 // 使用一个全局 pair 存放最小的和 // 记录当前最小和, first 为和, second 为叶子节点值 pair<int, int> MIN_SUM; void setToMinSum(int sum, int nodeValue) { if ( sum < MIN_SUM.first || (sum == MIN_SUM.first && nodeValue < MIN_SUM.second)) { MIN_SUM = make_pair(sum, nodeValue); } } // 找到 n 在 vt[begin, end) 中的下标,若找不到,则返回 end // 为了保证重复节点出现时,找到的下标是靠后的节点,这里从后往前找 int getIndex(const vector<int>& vt, int begin, int end, int n) { for (int i=end-1; i>=begin; i--) { if (vt[i] == n) return i; } return end; } // 根据中序与后序遍历创建树 // 中序:左根右 // 后序:左右根 // 算法:由上可以看到,从后序最后开始遍历,找到“根”,然后在中序中找到“根”, // 其左边就是左子树,右边就是右子树 // 针对中序遍历 inOrder[inBegin, inEnd) 中的部分建树 // 后序遍历 postOrder[inBegin, inEnd) 中的部分建树 void buildTree(const vector<int>& inOrder, int inBegin, int inEnd, const vector<int>& postOrder, int postBegin, int postEnd, int sum) { if (inEnd - inBegin == 1) { int root = postOrder[postBegin]; setToMinSum(sum + root, root); return; } if (inEnd - inBegin <= 0) return; // 后序的最后一位就是根节点 int root = postOrder[postEnd-1]; int rootIndex = getIndex(inOrder, inBegin, inEnd, root); int leftLength = rootIndex - inBegin; buildTree(inOrder, inBegin, rootIndex, postOrder, postBegin, postBegin + leftLength, sum + root); buildTree(inOrder, rootIndex + 1, inEnd, postOrder, postBegin + leftLength, postEnd - 1, sum + root); } int main(int argc, char const *argv[]) { #ifndef ONLINE_JUDGE freopen("548_i.txt", "r", stdin); freopen("uva_o.txt", "w", stdout); #endif // 输入 string inLine; string postLine; while (getline(cin, inLine) && getline(cin, postLine)) { MIN_SUM.first = numeric_limits<int>::max(); MIN_SUM.second = numeric_limits<int>::max(); int n; vector<int> inOrder, postOrder; // 读取一行中的各个 int istringstream issIn(inLine); while (issIn >> n) inOrder.push_back(n); istringstream issPost(postLine); while (issPost >> n) postOrder.push_back(n); // 建树,分析,输出 buildTree(inOrder, 0, inOrder.size(), postOrder, 0, postOrder.size(), 0); cout << MIN_SUM.second << endl; } return 0; }环境: C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE