uva112

来源:互联网 发布:淘宝网夹子 编辑:程序博客网 时间:2024/05/01 14:43

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.

This problem deals with determining whether binary trees represented as LISP S-expressions possess a certain property.

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.

picture25

Binary trees are represented in the input file as LISP S-expressions having the following form.

 empty tree  ::=  ()

tree ::= empty tree tex2html_wrap_inline118 (integer tree tree)

The tree diagrammed above is represented by the expression (5 (4 (11 (7 () ()) (2 () ()) ) ()) (8 (13 () ()) (4 () (1 () ()) ) ) )

Note that with this formulation all leaves of a tree are of the form (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.

The Output

There should be one line of output for each test case (integer/tree pair) in the input file. For each pairI,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.

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

yesnoyesno
做这个题花了很长一段时间,整整一天,而且也看了很多解题报告。。。主要对括号和空格不知道如何处理,也不知道如何建树,感觉那样太麻烦,也想不动,最后就看了一个牛人的代码,属于按照树的特点边读入边边递归处理,启发很大,就用C照着思路写了下,终于AC了,这题体会不少:1.要习惯二叉树的构造,学会根据输入来建树(虽然此题不用,但读入过程也是相仿的,学会这种思想)  2.原作者在读入过程中用的是C++的输入流cin可以很好的避开空格问题,还用到了强制转化,还有cin.clear()我是第一次见,据说可以在读入错误时返回到原读错位置,由于对C++的cin不太熟悉,最后还是用scanf()写的,虽然麻烦了些,但也不失为加深了印象。下面就把两份代码发来对照下吧,方便下次学习。
这份是我的代码:
#include<stdio.h>#include<stdlib.h>bool check(int sum,int aim,bool *root){//递归便读入边遍历二叉树,因为本身读入就是按先序遍历的      static  int num;     static char ch;     bool flag=false,right=false,left=false;     scanf("%c",&ch);//去掉前级左括号      while(ch==' '||ch=='\n')//把根本不需要的空格和回车撇开         scanf("%c",&ch);     if(!(*root=(scanf("%d",&num)==0))){//这里比较奇妙,因为肯定有人会想要没有数读怎么办比如空括号(),     //当没有数读的时候scanf()就会自动返回0,不信自己测试一下,同时这里故意用scanf()==0的形式是为了让flag赋值为下面作准备          sum+=num;         flag=check(sum,aim,&left);//左边          flag|=check(sum,aim,&right);//右边          if(right&&left)flag=(sum==aim);//在为叶节点时就进行一次判断      }     scanf("%c",&ch);//去掉后面的右括号      while(ch==' '||ch=='\n')        scanf("%c",&ch);     return flag;}int main(){    int aim;    bool root;    while(scanf("%d",&aim)==1){        printf("%s\n",check(0,aim,&root)?"yes":"no");    }    return 0;}

这份是原作者代码:
#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;}