2018-2019 ACM-ICPC, Asia Seoul Regional Contest F题(分类讨论)

 

给你一个表达式,首先判断是不是合法的C表达式,然后在这个题中,所有运算符没有优先级,只依靠括号决定运算顺序,所以挖掘出一个隐含的结论(划重点):有n个运算符的话,必须有n - 1对合法的括号(自然地每对括号里只有一个运算符和两个运算数)。判断时使用栈,然后就是考虑不符合正确C表达式的所有情况分类讨论就好。

注意:一个大bug就是,读入的表达式之间有空格,不能用scanf读入zi'fu'c

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn = 1010;
char str[maxn];
int id[maxn];

bool check()            //判断合法C表达式的函数
{
    int len = strlen(str);

    if(len == 1 && id[0] == 1)  return true;

    for(int i = 0; i < len; i++)
    {
        if(isalpha(str[i]))
            id[i] = 0;
        else if(str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '%')
        {
            id[i] = 1;
        }
        else if(str[i] == '(')              //(b+(a+c))+b         20120103310
            id[i] = 2;
        else
            id[i] = 3;
    }
    if(id[0] == 1 || id[len - 1] == 1)  {return false;}
    if(id[0] == 3 || id[len - 1] == 2)  {return false;}

    for(int i = 1; i < len; i++)
    {
        if(id[i - 1] == 0 && id[i] == 0)    {return false;}            //aa
        else if(id[i - 1] == 0 && id[i] == 2)   {return false;}        //a(
        else if(id[i - 1] == 1 && id[i] == 1)   {return false;}        //++
        else if(id[i - 1] == 1 && id[i] == 3)   {return false;}        //+)   
        else if(id[i - 1] == 2 && id[i] == 1)   {return false;}        //(+
        else if(id[i - 1] == 2 && id[i] == 3)   {return false;}        //()
        else if(id[i - 1] == 3 && id[i] == 0)   {return false;}        //)a
        else if(id[i - 1] == 3 && id[i] == 2)   {return false;}        //)(
    }

    int cnt = 0;
    for(int i = 0; i < len; i++)
    {
        if(id[i] == 2)  cnt++;
        else if(id[i] == 3)
        {
            if(!cnt)    return false;
            else    cnt--;
        }
    }
    return cnt == 0;
}


bool judge()            //判断
{
    stack<char> st;
    int sym = 0;
    int pnum = 0;

    int len = strlen(str);
    if(len == 1 && id[0] == 0)  return true;

    for(int i = 0; i < len; i++)
    {
        if(id[i] == 0)  continue;
        if(id[i] == 1)
        {
            st.push(str[i]);    sym++;
        }
        else if(id[i] == 2)
        {
            st.push('(');
        }
        else if(id[i] == 3)
        {
            int inner = 0;
            while(!st.empty())
            {
                //别先单独写一个st.top放在循环外同时while(st.top()!='(',因为正确表达式一对括号中就一个运算符,这样导致进入后即退出,inner一直为0,隐形bug...
                char ch = st.top();                     
                st.pop();
                if(ch == '(')   break;
                else    inner++;
                
            }
 
            if(inner != 1)  return false;            //只能为1
            else    pnum++;            //括号对数
        }
    }

    return pnum == sym - 1;            //括号对数是否等于运算符数-1
}



int main()
{
    //scanf("%s", str);         WA point!!!
    gets(str);
    int tot = 0;
    int len = strlen(str);
    for(int i = 0; i < len; i++)
    {
        if(str[i] != ' ')
            str[tot++] = str[i];
    }
    str[tot] = 0;
    bool formal = check();

    if(formal)
    {
        bool ok = judge();
        if(ok)  cout << "proper" << endl;
        else    cout << "improper" << endl;     
    }
    else
        cout << "error" << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38577732/article/details/89261997