【?】【7007】栈、模拟
Time Limit: 10 second 
Memory Limit: 2 MB
问题描述 
对一个只含单个大写英文字母,”+”,”-“,”(“和”)”的表达式,其中单个大写英文字母表示变量,进行如下处理:去掉表达式中的全部括号,并对”+”,”-“进行相应的变号,最后得到一个与所给表达式等价且长度最短的表达式。
Input
一个字符串,如(-A)-((-B)-(-C))
Output
一个字符串,如-A+B-C(长度为6)
Sample Input
(-A)-((-B)-(-C))
Sample Output
-A+B-C
【题目链接】:http://noi.qz5z.com/viewtask.asp?id=7007
【题解】 
 
输入的时候不能有无意义的嵌套像是(-(-A))什么的;下面这个程序不支持取反操作。。它只会把’-‘当做普通的减法; 
然后脱括号则运行得很好; 
思路就是遇到一个左括号就入栈; 
同时记录这个左括号左边一个字符是什么; 
遇到右括号就根据左括号的左边那个字符做相应的事情; 
减法的话,把当前处理的这个括号里面的加法变成减法,减法变成加法就好;去掉括号就好; 
 
【完整代码】
#include <cstdio>
#include <iostream>
#include <string>
#include <stack>
using namespace std;
string s1;
stack <int> a;
int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    cin >> s1;
    s1 = " ("+s1+')';
    int len = s1.size()-1;
    int i = 1;
    while (i <= len)
    {
        if (s1[i] == '(')
        {
            a.push(i-1);
            i++;
        }
        else
            if (s1[i] == ')')
            {
                s1.erase(i,1);
                switch (s1[a.top()])
                {
                case '(':
                    s1.erase(a.top()+1,1),i--;
                    break;
                case '+':
                    {
                        if (s1[a.top()+2] == '-')
                            s1.erase(a.top(),2),i-=2;
                        else
                            s1.erase(a.top()+1,1),i--;
                        break;
                    }
                case '-':
                    {
                        for (int j = a.top()+2;j <= i-1;j++) //把当前处理的这个括号内的符号变一下
                            {
                                if (s1[j] == '-')
                                    s1[j] = '+';
                                else
                                    if (s1[j] == '+')
                                        s1[j] = '-';
                            }
                        if (s1[a.top()+2] == '+')//如果这个括号右边一个字符原来是-号变成正号了前面那个符号就删掉;
                            s1.erase(a.top(),2),i-=2;
                        else
                            s1.erase(a.top()+1,1),i--;
                            //如果这个括号右边一个字符是数字;说明是一个正数,前面那个负号刚好保留,表示这个数变成负数,括号里面的符号上面已经变过了;
                        break;
                    }
                }
                a.pop();
            }
            else
                i++;
        len = s1.size()-1;
    }
    s1.erase(0,2);
    cout << s1<<endl;
    return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号