Lazy Math Instructor - POJ 1686 栈+提比的强行AC技能

Lazy Math Instructor
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3458 Accepted: 1174

Description

A math instructor is too lazy to grade a question in the exam papers in which students are supposed to produce a complicated formula for the question asked. Students may write correct answers in different forms which makes grading very hard. So, the instructor needs help from computer programmers and you can help. 

You are to write a program to read different formulas and determine whether or not they are arithmetically equivalent. 

Input

The first line of the input contains an integer N (1 <= N <= 20) that is the number of test cases. Following the first line, there are two lines for each test case. A test case consists of two arithmetic expressions, each on a separate line with at most 80 characters. There is no blank line in the input. An expression contains one or more of the following: 
  • Single letter variables (case insensitive). 
  • Single digit numbers. 
  • Matched left and right parentheses. 
  • Binary operators +, - and * which are used for addition, subtraction and multiplication respectively. 
  • Arbitrary number of blank or tab characters between above tokens.

Note: Expressions are syntactically correct and evaluated from left to right with equal precedence (priority) for all operators. The coefficients and exponents of the variables are guaranteed to fit in 16-bit integers. 

Output

Your program must produce one line for each test case. If input expressions for each test data are arithmetically equivalent, "YES", otherwise "NO" must be printed as the output of the program. Output should be all in upper-case characters.

Sample Input

3
(a+b-c)*2
(a+a)+(b*2)-(3*c)+c
a*2-(a+c)+((a+c+e)*2)
3*a+c+(2*e)
(a-b)*(a-b)
(a*a)-(2*a*b)-(b*b)

Sample Output

YES
YES
NO


题意:给你t组数据,每组数据有两行字符串,问你这两个字符串计算的结果是否相同,注意()的优先和*的优先级别。

思路:不知道为什么这样做可以AC,或者我们可以把下面这种做法理解成提比的强行AC技能(提比见图)。

                                                                                                                            

       对于每个a-z把它变成ASCII所对应的数,即97-124。然后运算,过程中用int即可,其实要是数据不水的话超long long 也是很有可能的,但不知为什么超了也能得到正确的结果,可能是原来的数一样大,超完int后也一样大吧。然后对于* + - 我用-999997983、-999997973、-999997963代替,(我假设它没有出现这样的中间数据→_→)。如果不放心的话struct node { }判断它的类型也行,就是麻烦点。

       用两个栈,A栈先存放数据,当读到一个 ')' 的时候,让A栈的数先转移到B栈,转移的时候将*的运算都做出来,然后再由B栈转移到A栈,这时再将+-的运算做出来,这样就能保证优先级了。

       PS:题目有说字符串中间可能会有空格。


提比强行AC的代码如下:

#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
char s[1010];
stack<int> st1;
stack<int> st2;
int num[1010];
int len;
int solvechar(char a) //将字符转换成数字
{ if(a==' ')
   return -10;
  else if(a=='(')
   return -999997993;
  else if(a==')')
   return -2;
  else if(a=='+')
   return -999997983;
  else if(a=='-')
   return -999997973;
  else if(a=='*')
   return -999997963;
  int k=a-'0';
  if(k>=0 && k<=9)
   return k;
  k=a-'a'+97;
  return k;
}
void jisuan()
{ int a,b,c,d,k;
  while(!st1.empty() && st1.top()!=-999997993)//先将st1中到(前的东西转移到st2中
  { k=st1.top();
    st1.pop();
    if(k==-999997963)    //计算乘法
    { a=st1.top();
      st1.pop();
      b=st2.top();
      st2.pop();
      c=a*b;
      st2.push(c);
    }
    else
     st2.push(k);
  }
  if(!st1.empty())   //除去(
   st1.pop();
  while(!st2.empty())  //将st2中的数转移回st1
  { k=st2.top();
    st2.pop();
    if(k==-999997983)  //计算加法
    { a=st1.top();
      st1.pop();
      b=st2.top();
      st2.pop();
      c=a+b;
      st1.push(c);
    }
    else if(k==-999997973)  //计算减法
    { a=st1.top();
      st1.pop();
      b=st2.top();
      st2.pop();
      c=a-b;
      st1.push(c);
    }
    else
     st1.push(k);
  }
}
int solve()
{ len=strlen(s);
  int i,j,k,pos=0,m=0;
  for(i=0;i<=len-1;i++)
  { k=solvechar(s[i]);
    if(k==-10)
     continue;
    if(k==-2)  //每次到)的时候进行计算
     jisuan();
    else
     st1.push(k);
  }
  jisuan();
  return st1.top();
}
int main()
{ int t,ans1,ans2;
  scanf("%d",&t);
  getchar();
  while(t--)
  { gets(s);
    ans1=solve();
    st1.pop();
    gets(s);
    ans2=solve();
    st1.pop();
    if(ans1==ans2)
     printf("YES\n");
    else
     printf("NO\n");
  }
}

再附上网上的测试数据和运行出来的结果,我又加了两个ans分别为多少。

15
2 *    1-3+(        2    *           5   )
9
8
      ((2    *   4)-7*2+(5-(6   * 7)+   4 )   )
(a)+(((b)))*(a-(2*b))*(1)*(b-2+c+a)*(d+e+a-f+b)
a    *    b    *      a * b * a * a * 9 * b * a * 8 * b * 7 * c * 9 * a
(((a)*a)*a  * b  * (     a-b)*(   a -   b   )*(a-c)*(a+b))*(((b-c)))
b*a*(a*(a*(b-c))*((a+b)*(a-c))*(a-b)*(a-b))
(w-a)+(a-b)-(c+a)*4+d
(a-w)+(b-a)-(a+c)*d+4
a-b*c+a+d*a-c*a+e*a*b*9*z*8*w*7
(a*a*a*a*b*(c-b+1)+(a*b*(a*(a*d-c)+e)))*9*z*8*w*7
(a+b-c)*2
(a+a)+(b*2)-(3*c)+c
a*2-(a+c)+( (a+c+e)*2)
3*a+c+(2*e)
(a-b)*(a-b)
(a*a)-(2*a*b)-(b*b)
(a-b)*(a-b)
(a*a)-(2*a*b)+(b*b)
a*b
b*a
1+a-a
b+1-b
2+1+a+1
1+3+a
(1+a+b)+7  +c+(d)
a+c+b+d +1+1+(1+(2+3))
((((1)+a)+b))+6  +c+(d)
a+c+b+d +1+1+(1+(2+3))

15
2 *    1-3+(        2    *           5   )
9
ans 9 9
YES
8
      ((2    *   4)-7*2+(5-(6   * 7)+   4 )   )
ans 8 -39
NO
(a)+(((b)))*(a-(2*b))*(1)*(b-2+c+a)*(d+e+a-f+b)
a    *    b    *      a * b * a * a * 9 * b * a * 8 * b * 7 * c * 9 * a
ans -832897199 758784640
NO
(((a)*a)*a  * b  * (     a-b)*(   a -   b   )*(a-c)*(a+b))*(((b-c)))
b*a*(a*(a*(b-c))*((a+b)*(a-c))*(a-b)*(a-b))
ans 522623692 522623692
YES
(w-a)+(a-b)-(c+a)*4+d
(a-w)+(b-a)-(a+c)*d+4
ans -663 -19617
NO
a-b*c+a+d*a-c*a+e*a*b*9*z*8*w*7
(a*a*a*a*b*(c-b+1)+(a*b*(a*(a*d-c)+e)))*9*z*8*w*7
ans -1401776035 -1368750848
NO
(a+b-c)*2
(a+a)+(b*2)-(3*c)+c
ans 192 192
YES
a*2-(a+c)+( (a+c+e)*2)
3*a+c+(2*e)
ans 592 592
YES
(a-b)*(a-b)
(a*a)-(2*a*b)-(b*b)
ans 1 -19207
NO
(a-b)*(a-b)
(a*a)-(2*a*b)+(b*b)
ans 1 1
YES
a*b
b*a
ans 9506 9506
YES
1+a-a
b+1-b
ans 1 1
YES
2+1+a+1
1+3+a
ans 101 101
YES
(1+a+b)+7  +c+(d)
a+c+b+d +1+1+(1+(2+3))
ans 402 402
YES
((((1)+a)+b))+6  +c+(d)
a+c+b+d +1+1+(1+(2+3))
ans 401 402
NO



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值