POJ 2106-Boolean Expressions,双栈运用类似表达式求值!

                                               Boolean Expressions

   首先声明此题后台可能极水(毕竟这种数据不好造!)。昨天写了一天却总是找不到bug,讨论区各种数据都过了,甚至怀疑输入有问题,但看到gets也可以过,难道是思路错了?

    题意:V表示ture,F表示false,然后有三种位运算符‘!’、‘&’、'|'。其中'!'的优先级最高,‘|’的优先级最低。即优先级关系:! > & > | 。给你一串包含这些运算符的表达式当然了还有括号,要你判断最终结果是VorF。

    先说说我的思路吧:符号栈和数值栈肯定是前提(数组模拟也无所谓)。由于‘!’和‘&’的运算等级较高,于是我们可以先把所有的‘!’和‘&’先进行运算,最后运算或(扫一遍无先后)。当然了,括号的优先级最最高,我们特判括号的情况。你可能要问‘!’和’&‘的优先级有大小,怎么判断先后呢,我们发现’!‘一般是在一个数值前面,当存入一个数值的时候可以直接运算,’&‘在两个数值之间,也是直接取数值栈顶的两个元素直接运算再入栈。就是因为’!‘只能在一个数值前或者括号前(括号内最终也会化为一个数值),所以如果’!‘和’&‘都出现了肯定会将’!‘先运算完再’&‘运算,本来也符合题意优先级之分。但为什么会wa这么多遍呢,next....

    现在来说说括号怎么判,我们如果是出现'('的话直接先入符号栈,然后数值和符号也是直接入相应的栈再判断运算。但当’)‘出现意味着肯定有一个最近的’(‘与其配对,我们这时就要把括号里的先运算完对吧,但上述提到’!‘和’&‘都是一出现就直接运算了,所以这时的括号内只能是单个数值或很多’|‘,还是直接运算,到’(‘就截止了嘛。最后弹出’(‘。好像看起来没毛病,又是WA。原因为何?next.....

    最后看其他人提交的代码结果发现他们根本没有判优先级,三种符号出现都是从左往右扫,这样也过?’!‘的情况肯定没问题,但’&‘和’|‘总得有个先后,一学弟给出一幅图画出单个’&‘和单个’|‘的所有情况让我猜想这样依次运算是否和先后运算的结果一样?草草的证明了一下貌似真的可以(急功近利),然后仿照这大家的思路做了做终于发现自己的问题出在哪了,原来在进行’!‘和’&‘运算的时候没有判断到’(‘应截止。还有在’(‘应当出栈的时候没有判断栈顶元素是否为’(‘。也是神奇,我的正确思路居然被这种样例hackde。这时仍接受着依次运算和先后运算的结果一样的观点,回到宿舍学姐再讨论群里提出这样一组数据:1|0&0 即 V|F&F。这样明显打破上述观点,然后用两种代码都试了试果然依次运算的结果是F,正解应该是V。不得不说自己没有仔细证明为了A题草草下定结论,不过所幸自己的代码是没有问题的。可能大家读题题意没有明确,却阴差阳错,集训队的读题能力貌似一直处于迷离状态。。。。

    重(ji)点(tang):研究性学习真的是让人很兴奋,充分锻炼一个人的耐心与思维,在结论成果得出的那一刻仿佛即将升天般的快感,这种学习方式也值得我们利用,当前学习状态不禁让我想起了快餐文化这一概念,急功近利总不得有好的结果,沉心静气淡泊名利才能走的更远。不惜花了这么大的篇幅来引出这段话,就算个人体验了,不喜勿喷。

    回到原题,下面给出三种代码:

 思路1:WA。未正确判断好括号关系。

const int N=1e6+10;
stack<char>q1;
stack<int>q2;
char s[150];
void ch(char c)
{
    if(c=='!')
    {
        int x1=q2.top();q2.pop();
        x1=!x1;
        q2.push(x1);
    }
    else if(c=='&')
    {
        int x1=q2.top();q2.pop();
        int x2=q2.top();q2.pop(); 
        q2.push(x1&x2);
    }
    else if(c=='|')
    {
        int x1=q2.top();  q2.pop();
        int x2=q2.top();  q2.pop();
        q2.push(x1|x2);
    }
    q1.pop();
}
int main()
{
    int t=1;
    char c;
    while(1)
    {
        c=getchar();
        if(c==' ') continue;
        if(c=='\n'||c==EOF)
        {
            while(!q1.empty())
            {
                if(q1.top()!='(') ch(q1.top());
                else q1.pop();
            }
            printf("Expression %d: ",t++);
            if(q2.top()==1) puts("V");
            else puts("F");
            while(!q1.empty()) q1.pop();
            while(!q2.empty()) q2.pop();
			if(c==EOF) break;
			else continue;
        }
        if(c==')')
        {
            while(!q1.empty()&&q1.top()!='(') ch(q1.top());
            q1.pop();//本意是删去‘(’,但应该判断是否为空且栈顶是否为‘(’
        }
        else
        {
            if(c!='V'&&c!='F') q1.push(c);
            else
            {
                if(c=='V') q2.push(1);
                else q2.push(0);
                while(!q1.empty())//应该判断‘(’截止
                {
                    if(q1.top()!='!'&&q1.top()!='&') break;//‘!’和'&'优先
                    ch(q1.top());
                }
            }
        }
    }
    return 0;
}


  代码二:AC。

const int N=1e6+10;
stack<char>q1;
stack<int>q2;
char s[N];
void ch(char c)
{
    if(c=='!')
    {
        int x=q2.top();
        q2.pop();
        q2.push(!x);
    }
    else if(c=='&')
    {
        int x1=q2.top();
        q2.pop();
        int x2=q2.top();
        q2.pop();
        q2.push(x1&x2);
    }
    else if(c=='|')
    {
        int x1=q2.top();
        q2.pop();
        int x2=q2.top();
        q2.pop();
        q2.push(x1|x2);
    }
    q1.pop();
}
int main()
{
    int t=1;
    while(gets(s))
    {
        while(!q1.empty()) q1.pop();
        while(!q2.empty()) q2.pop();
        int len=strlen(s);
        for(int i=0; i<len; i++)
        {
            if(s[i]==' ') continue;
            if(s[i]==')')
            {
                while(!q1.empty()&&q1.top()!='(')  ch(q1.top());
                if(!q1.empty()&&q1.top()=='(') q1.pop();//删去左括号
            }
            else
            {
                if(s[i]!='F'&&s[i]!='V') q1.push(s[i]);
                else
                {
                    if(s[i]=='F') q2.push(0);
                    else q2.push(1);
                    while(!q1.empty()&&q1.top()!='(')
                    {
                        if(q1.top()!='&'&&q1.top()!='!') break;
                        ch(q1.top());
                    }
                    if(!q1.empty()&&q1.top()=='(') q1.pop();
                }
            }
        }
        printf("Expression %d: ",t++);
        while(!q1.empty()) ch(q1.top());
        if(q2.top()==1) puts("V");
        else puts("F");
    }
    return 0;
}


  代码三:hacked   V|F&F

const int N=1e3+10;
stack<char>q1;
stack<int>q2;
char s[N];
void deal(char tmp)
{
    if(tmp==')') q1.pop();
    else
    {
        if(tmp=='V') q2.push(1);
        else q2.push(0);
    }
    while(!q1.empty()&&q1.top()!='(')
    {
        char c=q1.top();
        q1.pop();
        if(c=='!'&&!q2.empty())
        {
            int x=q2.top();
            q2.pop();
            q2.push(!x);
        }
        else if(c=='&'&&q2.size()>1)
        {
            int x1=q2.top();
            q2.pop();
            int x2=q2.top();
            q2.pop();
            q2.push(x1&x2);
        }
        else if(c=='|'&&q2.size()>1)
        {
            int x1=q2.top();
            q2.pop();
            int x2=q2.top();
            q2.pop();
            q2.push(x1|x2);
        }
    }
}
int main()
{
    int t=1;
    while(gets(s))
    {
        while(!q1.empty()) q1.pop();
        while(!q2.empty()) q2.pop();
        int len=strlen(s);
        for(int i=0; i<len; i++)
        {
            if(s[i]==' ') continue;
            if(s[i]=='F'||s[i]=='V'||s[i]==')') deal(s[i]);
            else q1.push(s[i]);
        }
        printf("Expression %d: ",t++);
        if(!q1.empty()) deal(q1.top());
        if(q2.top()==1) puts("V");
        else puts("F");
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值