読者です 読者をやめる 読者になる 読者になる

土下座しながら探索中

主に競技プログラミング

UVa 112 : Tree Summing

UVa 構文解析

問題リンク:Tree Summing

問題概要:
integer I と2分木がLISP S-expressionでtreeとして与えられる
treeのルートから葉までの値の和がIとなるならyes,ならないならnoと出力せよ

解法:
構文解析を行う
treeの値がマイナスである事があるので注意すること
つまり、(-10()(2()()))みたいなtreeもあり得る

コード:

#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cassert>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)

using namespace std;

int I;
bool found;
string tree;
int cur;

void dfs(int cost)
{
  assert(tree[cur] == '(');
  cur++;
  int value = 0;
  bool minus = false;
  if(tree[cur] == '-')
    {
      minus = true;
      cur++;
    }
  while('0' <= tree[cur] && tree[cur] <= '9')
    {
      value = value * 10 + (tree[cur]-'0');
      cur++;
    }
  if(minus)value*=-1;
  assert(tree[cur] == '(');

  bool in = false;
  if(tree.substr(cur,2) != "()")
    {
      in = true;
      dfs(cost+value);
      cur++;
    }
  else cur += 2;

  if(tree.substr(cur,2) != "()")
    {
      in = true;
      dfs(cost+value);
      cur++;
    }
  else cur += 2;

  if(!in)
    {
      if(cost+value == I)
	{
	  found = true;
	}
    }

}

int main()
{
  while(cin >> I)
    {
      cur = 0;
      found = false;
      tree.clear();
      cin.ignore();
      string s;
      int stk = 0;
      while(getline(cin,s))
	{
	  tree += s;
	  rep(i,s.size())
	    {
	      if(s[i] == '(')stk++;
	      else if(s[i] == ')')stk--;
	    }
	  if(stk == 0)break;
	}
      string pre = tree;
      tree.clear();
      rep(i,pre.size())if(pre[i] != ' ')tree += pre[i];
      //cout << "tree : " << tree << endl;

      if(tree == "()")
	{
	  cout << "no" << endl;
	  continue;
	}

      dfs(0);

      cout << (found?"yes":"no") << endl;

    }
  return 0;
}