Problem B: Tree Summing

/*
Description
LISP是最早的高级程序设计语言中的一种,和FORTRAN一样,也是目前还在使用的最老的语言之一。LISP中使用的基本的数据结构是列表,可以用来表示其他重要的数据结构,比如树。

本问题判断由LISP的S-表达式表示的二叉树是否具有某项性质。

给出一棵整数的二叉树,请写一个程序判定是否存在这样一条从树根到树叶的路,路上的结点的总和等于一个特定的整数。例如,在下图所示的树中有4条从树根到树叶的路,这些路的总和是27, 22, 26和18。
在输入中二叉树以LISP的S-表达式表示,形式如下。
empty tree ::= ()
tree ::= empty tree (integer tree tree)
在上图给出的树用表达式表示为(5 (4 (11 (7 () ()) (2 () ()) ) ()) (8 (13 () ()) (4 () (1 () ()) ) ) )。
在这一公式中树的所有树叶表示形式为(整数 () () ) 。
因为空树(empty tree)没有从树根到树叶的路,对于在一棵空树中是否存在一条路总和等于特定的数的查询回答是负数。


Input
输入包含一系列的测试样例,每个测试用例形式为整数/树,由一个整数,后面跟一个或多个空格,然后是一个以上述的S-表达式形式表示二叉树。所有二叉树的S-表达式是有效的,但表达式可能占据几行,也可能包含若干空格。输入文件中有一个或多个测试用例,输入以文件结束符结束。

Output
对输入中每个测试用例(整数/树)输出一行。对每一个I,T (I是整数,T是树),如果在T中存在从根到叶的总和是I的路,则输出字符串yes;如果没有从根到叶的总和是I的路,则输出字符串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

*/

#include <bits/stdc++.h>
#define long long int int
  
using namespace std;
 
 
int sum;
string tree;
 
int parse( int cur, int l, int r )
{
    if( r - l == 2 )
    {
        return -1;
    }
 
    int val = 0, sign = 1;
    int idx = l + 1;
     
    if( tree[idx] == '-' )
    {
        sign = -1;
        idx++;
    }
     
    for( ; idx < r; idx++ )
    {
        if(tree[idx] == '(' )
        {
            break;
        }
        else
        {
            val = val * 10 + tree[idx] - '0';
        }
    }
     
    val = val * sign;
 
    int tempidx = idx;
    int  pcount = 0;
     
    for( ; tempidx < r; tempidx++ )
    {
        if( tree[tempidx] == '(' )
        {
            pcount++;
        }
        else if( tree[tempidx] == ')')
        {
            pcount--;
        }
         
        if( pcount == 0 )
        {
            break;
        }
    }
 
 
    int res1 = parse( cur + val, idx, tempidx + 1 );
 
    idx = tempidx + 1;
     
    int res2 = parse (cur + val, idx, r - 1 );
 
    if ( res1 == -1 && res2 == -1 )
    {
        return cur + val == sum;
    }
    else
    {
        if (res1 == -1) return res2;
        if (res2 == -1) return res1;
        return res1 | res2;
    }
}
 
bool solve()
{
    int pcount = -1;
    char ch;
    tree = "";
 
 
    do
    {
        ch = getchar();
         
        if( isdigit(ch) || ch == '(' || ch == ')' || ch == '-' )
        {
            tree += ch;
            if( ch == '(' )
            {
                if( pcount == -1 )
                {
                    pcount = 0;
                }
                pcount++;
            }
            else if( ch == ')' )
            {
                pcount--;
            }
        }
    } while (pcount != 0);
 
 
    int res = parse( 0, 0, tree.length() );
     
    if( res == -1 )
    {
        res = 0;
    }
     
    return res;
}
 
int main()
{
    while( cin >> sum )
    {
        if( solve() )
        {
            printf("yes\n");
        }
        else
        {
            printf("no\n");
        }
    }
 
    return 0;
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值