zoukankan      html  css  js  c++  java
  • 布尔表达式

    题目链接:http://noi.openjudge.cn/ch0303/6263/
    总时间限制: 1000ms    内存限制: 65536kB
    描述

    输入一个布尔表达式,请你输出它的真假值。 比如:( V | V ) & F & ( F | V ) 
    V表示true,F表示false,&表示与,|表示或,!表示非。 
    上式的结果是F

    输入
    输入包含多行,每行一个布尔表达式,表达式中可以有空格,总长度不超过1000
    输出
    对每行输入,如果表达式为真,输出"V",否则出来"F"
    样例输入
    ( V | V ) & F & ( F| V)
    !V | V & V & !F & (F | V ) & (!F | F | !V & V)
    (F&F|V|!V&!F&!(F|F&V))
    样例输出
    F
    V
    V
    分析:(来源:http://blog.csdn.net/INCINCIBLE/article/details/51151222?locationNum=5&fps=1)
    原理很简单,将中缀表达式转化为前缀表达式在计算,只是代码实现比较麻烦。
    中缀转前缀的步骤如下:
    (1) 首先构造一个运算符栈(也可放置括号),运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。
    (2)从右至左扫描中缀表达式,从右边第一个字符开始判断:
    如果当前字符是数字,则分析到数字串的结尾并将数字串直接输出。
    如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将运算符直接入栈;否则将栈顶运算符出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。
    如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇左括号前将所有的运算符全部出栈并输出,遇右括号后将左右的两括号一起删除。
    (3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。中缀表达式也就转换为前缀表达式了。
     
    右括号有最高的优先级,左括号优先级最低。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<stack>
     6 #include<cstring>
     7 using namespace std;
     8 char calculate(char x, char y,char oper )// 计算 x oper y 
     9 {
    10     bool a=(x=='V'),b=(y=='V'),ans;
    11     if(oper=='|') ans=(a||b);
    12     else if(oper=='&') ans=(a&&b);
    13     return ans?'V':'F';
    14 }
    15 char reverse(char x) //将逻辑值取反。其实就是‘!’运算符 
    16 {
    17     if(x=='V')return 'F';
    18     return 'V';
    19 }
    20 int main()
    21 {
    22     string in;
    23     int i,j,len;
    24     
    25     while(getline(cin,in))
    26     {
    27         stack<char> Oper,num; //oper保存运算符,num保存运算结果 
    28         queue<char> s;        //s就是前缀表达式 
    29         len=in.length();
    30         i=len;
    31         in=" "+in;
    32         while(i>0)// 从右往左,中缀表达式转前缀表达式 
    33         {
    34             if(in[i]==' ')
    35             {
    36                 i--;continue;
    37             }
    38             else if(isalpha(in[i])) s.push(in[i--]);//isalpha()函数:如果参数是字母字符,函数返回非零值,否则返回零值
    39             else if(in[i]=='!')  s.push(in[i--]);    //最高级的运算,直接进入表达式(这里主要是因为!运算符是单目运算符) 
    40             else
    41             {
    42                 if(in[i]=='&'||in[i]=='|'||in[i]==')')  //低级运算,进栈 
    43                     Oper.push(in[i--]);
    44                 else if(in[i]=='(')  //一个括号结束,弹出中间的所有运算符 
    45                 {  
    46                     while(Oper.top()!=')')
    47                     {
    48                         s.push(Oper.top());
    49                         Oper.pop();
    50                     }
    51                     Oper.pop();
    52                     i--;
    53                 }
    54             }
    55         }
    56         while(!Oper.empty())  //栈中剩下的运算符 
    57             s.push(Oper.top()),Oper.pop();
    58         
    59         while(!s.empty())  //计算前缀表达式 
    60         {       
    61             char ch=s.front(); s.pop();
    62             if(isalpha(ch))  num.push(ch);
    63             else Oper.push(ch);
    64             if(!num.empty()&&!Oper.empty()&&Oper.top()=='!')  //单目运算符‘!’;
    65             {   
    66                 char x=num.top();
    67                 num.pop();Oper.pop();
    68                 num.push(reverse(x));
    69             }
    70             else if(num.size()>=2&&!Oper.empty())  //双目运算符 
    71             {
    72                 char oper=Oper.top(),x,y;
    73                 Oper.pop();
    74                 x=num.top();num.pop();
    75                 y=num.top();num.pop();
    76                 num.push(calculate(x,y,oper));
    77             }
    78         }
    79         cout<<num.top()<<endl;
    80     }
    81 }

    另外,可以参考http://www.ithao123.cn/content-10400535.html

     第二种思路,递归求解。

    代码来源:北大郭炜老师MOOC课程的代码。可以参考中缀表达式计算这篇文章的分析。

      1 #include <iostream>
      2 #include <cstdio>
      3 using namespace std;
      4 
      5 char wholeExp[1500];//表示整个表达式的字符串 
      6 int ptr = 0;
      7 
      8 bool exp();//读入一个表达式并返回其值 
      9 bool item();//读入一个项并返回其值 
     10 bool factor();//读入一个因子并返回其值 
     11 bool notExp();//将表达式取反的操作
     12 /*
     13 表达式:由单独的"项"或者"项"与"|"运算符连接形成;
     14 项:由单独的"因子"或"因子"和&运算符连接而成;
     15 因子:可以是单独的V或F,也可以是用括号括起来的"表达式"。
     16 */
     17 int main()
     18 {
     19     freopen("6263.in","r",stdin);
     20     int t = 1;//表示第t个测试样例 
     21     char c;
     22     int i = 0;
     23     int n = EOF + 1;
     24     while(n != EOF) 
     25     {
     26         n = scanf("%c",&c);
     27         if( n == EOF || c == '
    ') 
     28         {
     29             wholeExp[i] = '';
     30             if( i > 0) 
     31             {
     32                 ptr = 0;
     33                 bool res = exp();
     34                 if (res) { printf("Expression %d: V
    ",t++); }
     35                 else printf("Expression %d: F
    ",t++);
     36                 /*if (res) { printf("V
    ",t++); }
     37                 else printf("F
    ",t++);*/
     38             }
     39             i = 0;
     40         }
     41         else if( c != ' ') wholeExp[i++] = c;
     42     }
     43     return 0;
     44 }
     45 
     46 bool exp() //读入一个表达式并返回其值 
     47 {
     48     bool result = item();
     49     while(wholeExp[ptr] == '|' ) 
     50     {
     51         ++ptr;
     52         result = result | item();//注意:这里的或运算不能用C语言逻辑或运算符,因为逻辑或运算符在编译器处理完以后有短路特性,可能会忽略后面的输入。比如(V|V)&F,若是用逻辑或,可能只扫描到第一个V就返回逻辑真,不再继续往后扫描了。但是其实应该是逻辑假。
     53     }
     54     return result;
     55 }
     56 
     57 bool item() //读入一个项并返回其值  
     58 {
     59     bool result = factor();
     60     while(wholeExp[ptr] == '&') 
     61     {
     62         ++ptr;
     63         result = result & factor();//同样地,这个地方不能用逻辑与运算符,否则会错忽略后面应该扫描的东西从而返回错误的结果。比如(F&V)|V。
     64     }
     65     return result;
     66 }
     67 
     68 bool factor() //读入一个因子并返回其值 
     69 {
     70     bool result;
     71     switch( wholeExp[ptr]) 
     72     {
     73         case 'F':
     74             ++ptr;
     75             return false;
     76             break;
     77         case 'V':
     78             ++ptr;
     79             return true;
     80             break;
     81         case '(':
     82             ++ptr;
     83             result = exp();
     84             ++ptr; //skip ')'
     85             return result;
     86             break;
     87         case '!':
     88             result = notExp();
     89             return result;
     90             break;
     91     }
     92 }
     93 
     94 bool notExp() //将表达式取反的操作
     95 {
     96     //wholeExp[ptr] == '!' when called;
     97     ptr++;
     98     bool result;
     99     switch(wholeExp[ptr]) 
    100     {
    101         case 'F':
    102             ++ptr;
    103             return true;
    104             break;
    105         case 'V':
    106             ++ptr;
    107             return false;
    108             break;
    109         case '(':
    110             ++ptr;
    111             result = exp();
    112             ++ptr; //skip ')'
    113             return !result;
    114             break;
    115         case '!':
    116             result = notExp();
    117             return !result;
    118             break;
    119     }
    120 }
  • 相关阅读:
    poj3718 Facer's Chocolate Dream
    codeforces 917D Stranger Trees
    uoj#349 【WC2018】即时战略
    bzoj5153 [Wc2018]州区划分
    bzoj5152 [Wc2018]通道
    loj2001[SDOI2017]树点染色
    loj2000[SDOI2017]数字表格
    Atcoder arc092
    bzoj4826[hnoi2017]影魔
    bzoj4827 [hnoi2017]礼物
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/7240987.html
Copyright © 2011-2022 走看看