NYOJ1272 表达式求值(河南省第九届ACM省赛)

题目描述:

假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式。 2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+. 3. 如果 X 和 Y 是 表达式,则 函数 Smax(X,Y)也是表达式,其值为:先分别求出 X ,Y 值的各位数字之和,再从中选最大数。 4.如果 X 是 表达式,则 (X)也是表达式。 例如: 表达式 12*(2+3)+Smax(333,220+280) 的值为 69。 请你编程,对给定的表达式,输出其值。  

输入描述:

【标准输入】 第一行: T 表示要计算的表达式个数 (1≤ T ≤ 10) 接下来有 T 行, 每行是一个字符串,表示待求的表达式,长度<=1000 

输出描述:

【标准输出】 对于每个表达式,输出一行,表示对应表达式的值。

样例输入:

复制
3
12+2*3
12*(2+3)
12*(2+3)+Smax(333,220+280)

样例输出:

18
60
69


思路:

先看下面的链接 前缀、中缀、后缀 表达式及其求值,了解其思想

https://blog.csdn.net/antineutrino/article/details/6763722/

和普通的表达式求值比起来多了一种,Smax运算,这个运算的优先级和()相同

有了双栈的思想,模拟运算即可

只不过右括号有两种匹配方式,其中做点处理

详见代码


代码:

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<queue>
#include<stack>
#include<map>
using namespace std;

char s[1005];
map<char,int> mp;
stack<char> s2;//符号
stack<int> s1;//数字

int Smax(int a)
{
    int b = 0;
    while(a) b += a%10, a /= 10;
    return b;
}

void solve(int li)
{
    int a, b, c, d;
    while(!s2.empty() && mp[s2.top()] < li)
    {
        if(s2.top() == ',')
        {
            c = s1.top();
            s2.pop();
            s1.pop();
            continue;
        }
        a = s1.top(); s1.pop();
        b = s1.top(); s1.pop();
        if(s2.top() == '*') s1.push(a*b);
        if(s2.top() == '+') s1.push(a+b);
        s2.pop();
    }
    if(li == 2)
    {
        if(s2.top() == '<')
        {
            d = s1.top();
            s1.pop();
            a = Smax(c), b = Smax(d);
            s1.push(a > b ? a : b);
        }
        s2.pop();
    }
}

int main()
{
    mp['*'] = 0;
    mp['+'] = 0;
    mp[','] = 1;
    mp['<'] = 2;
    mp['('] = 2;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        int len = strlen(s);
        for(int i = 0; i < len; i++)
        {
            if(isdigit(s[i]))
            {
                int t = 0;
                while(isdigit(s[i]))
                {
                    t *= 10;
                    t += s[i] - '0';
                    i++;
                }
                i--;
                s1.push(t);
            }
            else if(s[i] == ')') solve(2); //如果是右括号,处理到一个出现 '<' 或者 '('
            else if(s[i] == '+') solve(1), s2.push('+'); //如果是+号,将栈顶的 * 和 + 处理干净
            else if(s[i] == 'S') s2.push('<'), i += 4;
            else s2.push(s[i]);//'('  ','  '*' 直接入栈
        }
        solve(10);//处理干净剩余的操作符
        printf("%d\n",s1.top());
        while(!s1.empty()) s1.pop();//其实不清空问题不大,但每做一次运算,内存消耗就会增加
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/j2_o2/article/details/80311446