Time limit: 3.000 seconds
限时:3.000秒
Background
背景
LISP was one of the earliest high-level programming languages and, with FORTRAN, is one of the oldest languages currently being used. Lists, which are the fundamental data structures in LISP, can easily be adapted to represent other important data structures such as trees.
LISP是一个最早的高级编程语言,而FORTRAN是现在仍在使用的最古老的语言。链表在LISP中是一个基本的数据结构,可以通过简单地修改使之能够表示其它更重要的数据结构,比如树。
This problem deals with determining whether binary trees represented as LISP S-expressions possess a certain property.
这个问题是要来确定一个由LISP的S表达式表示的树是否具有一个确定的性质。
The Problem
问题
Given a binary tree of integers, you are to write a program that determines whether there exists a root-to-leaf path whose nodes sum to a specified integer. For example, in the tree shown below there are exactly four root-to-leaf paths. The sums of the paths are 27, 22, 26, and 18.
给定一个整型值的二叉树,你要写一个程序确定是否存在一个由根到叶的路径,并且这条路径上的值之和等于指定值。比如在下面显示的树中,有且仅有4条由根到叶的路径。这些路径的和分别是27,22,26和18。
Binary trees are represented in the input file as LISP S-expressions having the following form.
在输入数据中用LISP的S表达式表示的二叉树具有如下形式。
empty tree ::= () tree ::= empty tree | (integer tree tree)
The tree diagrammed above is represented by the expression (5 (4 (11 (7 () ()) (2 () ()) ) ()) (8 (13 () ()) (4 () (1 () ()) ) ) )
上图中的树可用该表达式表示为(5 (4 (11 (7 () ()) (2 () ()) ) ()) (8 (13 () ()) (4 () (1 () ()) ) ) )
Note that with this formulation all leaves of a tree are of the form (integer () () )
注意在这个式子中树的所有叶子的表示形式均为(integer () () )
Since an empty tree has no root-to-leaf paths, any query as to whether a path exists whose sum is a specified integer in an empty tree must be answered negatively.
但是,空树不存在根到叶子的路径。对于一个空树的路径和的查询,无论指定任何整数作为查询条件都要得到否定的结果。
The Input
输入
The input consists of a sequence of test cases in the form of integer/tree pairs. Each test case consists of an integer followed by one or more spaces followed by a binary tree formatted as an S-expression as described above. All binary tree S-expressions will be valid, but expressions may be spread over several lines and may contain spaces. There will be one or more test cases in an input file, and input is terminated by end-of-file.
测试用例的输入由“整数/树”对的形式构成。每个测试用例头部是一个整数,跟着是一个或多个空格,接下来就是上面描述的S表达式表示的二叉树。所有二叉树的S表达式都是有效的,但表达式中间可能会插有多行或多个格式。在输入数据中可能会有一个或多个测试用例,整个输入由EOF结束。
The Output
输出
There should be one line of output for each test case (integer/tree pair) in the input file. For each pair I,T (I represents the integer, T represents the tree) the output is the string yes if there is a root-to-leaf path in T whose sum is I and no if there is no path in T whose sum is I.
在每个测试用例(“整树/树”对)下面跟一行输出。对于每对I,T(I表示整树,T表示树),如果存在一条由根到叶子的路径的和等于I,则输出yes,否则输出no。
Sample Input
输入示例
22 (5(4(11(7()())(2()()))()) (8(13()())(4()(1()()))))
20 (5(4(11(7()())(2()()))()) (8(13()())(4()(1()()))))
10 (3
(2 (4 () () )
(8 () () ) )
(1 (6 () () )
(4 () () ) ) )
5 ()
Sample Output
输出示例
yes
no
yes
no
Analysis
分析
这是一道简单的二叉树遍例问题。算法描述在代码的注释中已经很清楚了,有两个需要注意的地方。一是空树必须输入no。二是判断加和结构的地方必须是在叶子结点,左子树或右子树不为空都不能算叶子。
Solution
解答
#include <iostream> #include <string> using namespace std; //递归扫描输入的整棵树 bool ScanTree(int nSum, int nDest, bool *pNull) { static int nChild; //略去当前一级前导的左括号 cin >> (char&)nChild; //br用于递归子节点的计算结果,bNull表示左右子是否为空 bool br = false, bNull1 = false, bNull2 = false; //如果读入值失败,则该节点必为空 if (!(*pNull = ((cin >> nChild) == 0))) { //总和加上读入的值,遍例子节点 nSum += nChild; //判断两个子节点是否能返回正确的结果 br = ScanTree(nSum, nDest, &bNull1) | ScanTree(nSum, nDest, &bNull2); //如果两个子节点都为空,则本节点为叶,检验是否达到目标值 if (bNull1 && bNull2) { br = (nSum == nDest); } } //清除节点为空时cin的错误状态 cin.clear(); //略去当前一级末尾的右括号 cin >> (char&)nChild; return br; } //主函数 int main(void) { bool bNull; //输入目标值 for (int nDest; cin >> nDest;) { //根据结果输出yes或no cout << (ScanTree(0, nDest, &bNull) ? "yes" : "no") << endl; } return 0; }
作者:王雨濛;新浪微博:@吉祥村码农;来源:《程序控》博客 -- http://www.cnblogs.com/devymex/ 此文章版权归作者所有(有特别声明的除外),转载必须注明作者及来源。您不能用于商业目的也不能修改原文内容。 |