题目链接:http://nyoj.top/problem/1272

  • 内存限制:64MB 时间限制:1000ms

题目描述

假设表达式定义为:
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 \le T \le 10$)
接下来有 T 行, 每行是一个字符串,表示待求的表达式,长度<=1000 

输出描述

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

样例输入

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

样例输出

18
60
69

解题思路

首先我们需要明白这些运算符之间的优先关系:+,*低于左括号,且高于右括号,*高于+.
首先我们建立两个栈,一个栈寄存数字,一个栈寄存运算符。
1.建立并初始化栈,将表达式起始符‘#’压入字符栈,
2.一次读入表达式中的每个字符si,循环执行3-5,直到求出整个表达式的值为止,
3.若si是数字,求出数字,并压入数字栈,读取下一字符,
4.如果si是运算符,则弹出字符栈顶的运算符,和si进行优先权比较,根据结果做不同处理.
(1)若是小于,则si压入字符栈,读取下一字符,
(2)若是大于,则从数字栈中弹出两个数,并弹出字符栈顶的运算符,进行相应运算,结果压入数字栈中,
(3)若是等于,则字符栈的栈顶元素是‘(’,且si为‘)’,这时弹出字符栈顶的(,相当于脱去括号,然后读取下一字符.

#include <bits/stdc++.h>
using namespace std;
int Smax(char *s);
char Judge(char a, char b) {
    if (a == '#')
        return '<';
    if (a == '(' && b == ')')
        return '=';
    if (b == ')')
        return '>';
    if (a == '+') {
        if (b == '*' || b == '(')
            return '<';
        else return '>';
    }
    if (a == '*') {
        if (b == '(')
            return '<';
        else return '>';
    }
    if (a == '(')
        return '<';
}
int work(int a, char c, int b) {
    switch(c) {
        case '+': return a + b;
        case '*': return a * b;
    }
}
int Chenge(int x) {
    int temp = 0;
    while (x) {
        temp += x % 10;
        x /= 10;
    }
    return temp;
}
int Cal(char *s) {
    char c;
    int a, b;
    stack <char> S;
    stack <int> num;
    S.push('#');
    for (int i = 0; s[i]; ) {
        if (s[i] == ',') {
            while (S.top() != '#') {
                if (num.size() == 1)
                    return num.top();
                a = num.top(), num.pop();
                b = num.top(), num.pop();
                c = S.top(), S.pop();
                num.push(work(a, c, b));
            }
            return num.top();
        }
        else if (s[i] == 'S') {
            int px = -1, cnt = 0, px1;
            for (int j = i; s[j] && !~px; j++) {
                if (s[j] == '(' && !cnt)
                    px1 = j;
                if (s[j] == '(')
                    cnt++;
                else if (s[j] == ')')
                    cnt--;
                if (!cnt && s[j] == ')')
                    px = j;
            }
            num.push(Smax(s + px1 + 1));
            i = px + 1;
        }
        else if (isdigit(s[i])) {
            int n, v;
            sscanf(s + i, "%d%n", &n, &v);
            num.push(n);
            i += v;
        }
        else {
            if (S.top() == '#' && s[i] == ')')
                return num.top();
            switch(Judge(S.top(), s[i])) {
                case '<': S.push(s[i]);
                    i++; break;
                case '>':
                    a = num.top(), num.pop();
                    b = num.top(), num.pop();
                    c = S.top(), S.pop();
                    num.push(work(a, c, b)); break;
                case '=': S.pop();
                    i++; break;
            }
        }
    }
    while (S.top() != '#') {
        a = num.top(), num.pop();
        b = num.top(), num.pop();
        c = S.top(), S.pop();
        num.push(work(a, c, b));
    }
    return num.top();
}
int Smax(char *s) {
    int px = 0, px2 = 0, cnt = 0;
    for (int i = 0; s[i]; i++) {
        if (s[i] == '(')
            cnt++;
        else if (s[i] == ')')
            cnt--;
        if (!cnt && s[i] == ',')
            px = i;
    }
    return max(Chenge(Cal(s)), Chenge(Cal(s + px + 1)));
}
int main() {
    int t;
    char s[1010];
    scanf("%d", &t);
    while(t--) {
        scanf("%s", s);
        printf("%d\n", Cal(s));
    }
    return 0;
}