• 数据结构——POJ 1686 Lazy Math Instructor 栈的应用


    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
    

    解题思路:我的程序是把每个 'a'--'z' 的字母分别hash成0--25             再把每个 'A'--'Z' 的字母分别hash成0--25

    大概题意:
    给出两个数学式子判断其结果是否相等。
    解法:
    1,用栈将表达式转换成为后缀式,然后计算后缀表达式的只判断其是否相等。
    2,其中有一个问题就是字母转换之后如何算其值来代表其字母的值,我用的是(int)s1[i]直接将其ASCII作为数值对待,结果也AC了(看来这个 题只是判断两个表达式是否在数值上是等价的而不是判断两个公式是否等价 比如说:(b-a+c)*2 与 (1+c)*2也相等,但是如果作为公式的话这两个是不相等的)。

    下面说一下中缀表达式转后缀表达式

    规则

    中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。

    转换过程需要用到栈,具体过程如下:

    1)如果遇到操作数,我们就直接将其输出。

    2)如果遇到左括号,我们直接将其放入到栈中。

    3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

    4)如果遇到任何其他的操作符,如(“+”, “*”,“-“)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。优先级从大到小顺序为:" * " 与 " / "," + " 与 " - ","(",也就是说" ( "优先级最低。

    5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

    规则

    规则很多,还是用实例比较容易说清楚整个过程。以上面的转换为例,输入为a + b * c + (d * e + f)*g,处理过程如下:

    1)首先读到a,直接输出。

    2)读到“+”,将其放入到栈中。

    3)读到b,直接输出。

    此时栈和输出的情况如下:

     

    4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。

    5)读到c,直接输出。

    此时栈和输出情况如下:

     

    6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级与读到的操作符" + "一样,所以也要弹出并输出。然后再将读到的" + "压入栈中。

    此时栈和输出情况如下:

     

    7)下一个读到的为"(",所以直接放入到栈中。

    8)读到d,将其直接输出。

    此时栈和输出情况如下:

     

    9)读到" * ",由于只有”(“的优先级最低,遇到" ) "的时候左括号"("才会弹出,所以" * "压入栈中。

    10)读到e,直接输出。

    此时栈和输出情况如下:

     

    11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。

    12)读到f,直接输出。

    此时栈和输出情况:

     

     

    13)接下来读到“)”,则直接将栈中元素弹出并输出直到遇到"("为止。这里右括号前只有一个操作符"+"被弹出并输出。

     

    14)读到" * ",压入栈中。读到g,直接输出。

     

    15)此时输入数据已经读到末尾,栈中还有两个操作符“*”和" + ",直接弹出并输出。

    至此整个转换过程完成。程序实现代码后续再补充了。

    然后是后缀表达式求值

    后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。假定待求值的后缀表达式为:6  5  2  3  + 8 * + 3  +  *,则其求值过程如下:

    1)遍历表达式,遇到的数字首先放入栈中,此时栈如下所示:

    2)接着读到“+”,则弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中。

    3)读到8,将其直接放入栈中。

    4)读到“*”,弹出8和5,执行8*5,并将结果40压入栈中。而后过程类似,读到“+”,将40和5弹出,将40+5的结果45压入栈...以此类推。最后求的值288。

    借鉴了高人的解题思路,自己不怎么表达的清楚

    程序代码:

    #include<iostream>
    #include <cstdio>
    #include<cstring>
    #define N 100
    using namespace std;
    int calculate(char s[],int t,int n)  //计算
    {
        if(n<t) return 0;
        if(n==t)
        {
            if(s[t]>='A' && s[t]<='Z') return (s[t]-'A');
            else
                if(s[t]>='a' && s[t]<='z') return (s[t]-'a');
                else return s[t]-'0';
        }
        int f1=-1,f2=-1;  //f1 : '+' 或者是 '-'的位子;f2 : '*'的位子
        int kuohao=0;
        for(int i=t;i<=n;i++)
        {
            if(s[i]=='(') kuohao++;
            else
                if(s[i]==')') kuohao--;
                else
                    if((s[i]=='+' || s[i]=='-') && kuohao==0) f1=i;
                    else
                        if(s[i]=='*' && kuohao==0) f2=i;
        }
        if(f1<0 && f2<0) return calculate(s,t+1,n-1);
        if(f1>0)
        {
            if(s[f1]=='+') return calculate(s,t,f1-1)+calculate(s,f1+1,n);
            else return calculate(s,t,f1-1)-calculate(s,f1+1,n);
        }
        else return calculate(s,t,f2-1)*calculate(s,f2+1,n);
    }
    void g(char s[])
    {   char *p=s;
        char temp[N],*p1=temp;
    
        while(*p!='')
        {
            while(((*p==' ') ||(*p=='	')) && (*p!='')) *p++;
            *p1=*p;
            p1++;
            p++;
        }
        *p1='';
        strcpy(s,temp);
    }
    int main()
    {
        int t;
       scanf("%d",&t);getchar();
        while(t--)
        {
            char str1[N],str2[N];
            gets(str1);
            gets(str2);
            g(str1);
            g(str2);
            int a=calculate(str1,0,strlen(str1)-1);
            int b=calculate(str2,0,strlen(str2)-1);
            if(a==b)cout<<"YES
    ";
            else cout<<"NO
    ";
        }
        return 0;
    }
    版权声明:此代码归属博主, 请务侵权!
  • 相关阅读:
    CSU 1505: 酷酷的单词【字符串】
    HDU 2036 改革春风吹满地【计算几何/叉乘求多边形面积】
    HDU 2034 人见人爱A-B【STL/set】
    HDU 2031 进制转换
    HDU 1020 Encoding【连续的计数器重置】
    HDU 1999 不可摸数【类似筛法求真因子和】
    动态规划总结
    CSU 1785: 又一道简单题
    CSU 1779: 错误的算法【矩阵/模拟】
    CSU 1777: 大还是小?【模拟/后导0】
  • 原文地址:https://www.cnblogs.com/www-cnxcy-com/p/4671702.html
Copyright © 2020-2023  润新知