6263:布尔表达式

  • 6263:布尔表达式
  • 优先级打表
  • 思路传送门


6263:布尔表达式

#include <bits/stdc++.h>
using namespace std;
#include <iomanip>
map<char,int> mp;
char piority[7][7]={
//行是操作数栈中的栈顶操作符,看优先级是否大于遍历表达式之后遇到的运算符 
//	|  & ! ( ) #
	{'>','<','<','<','>','>'},		//|
	{'>','>','<','<','>','>'},		//&
	{'>','>','=','<','>','>'},		//!
	{'<','<','<','<','=','0'},		//(   
	{'>','>','>','>','0','>'},		//)   
	{'<','<','<','<','0','='} 		//#
};
// ((<                                                                                                                                             
// )(>栈顶操作符是先遇到的操作符,如果可以出栈,说明栈顶操作符
//优先级大,并不代表后面表达式遇见的不要入栈,
// 即,后面遇见的要入栈不能说明栈顶优先级小 
 string removespace(string str){
	string s="";
	int len=str.size();
	for(int i=0;i<len;i++){
		if(str[i]!=' ')s+=str[i];
	}
	return s;
}
char cmp(char r,char c){
	int row=mp[r];
	int col=mp[c];
	return piority[row][col];
}
void solve(string s){
	char op[100];//操作符
	bool num[100];
//布尔值0或1表示,本来bool类型也可,!操作不用~,用1-num[ntop] 
	int otop=0,ntop=0;
	op[otop++]='#';
//用于表示优先级最小的操作符,省的判断栈空或表达式最后遇到空格
//不知如何比较 
	int len=s.size();
	for(int i=0;i<len;i++){
		if(s[i]=='V')num[ntop++]=1;
		else if(s[i]=='F')num[ntop++]=0;
		else {//那就是操作符了 
			char c=s[i];
			char r=op[otop-1];
			char res=cmp(r,c);
			while(res=='>'){
				r=op[otop-1];//不写这句就不对了,栈顶元素经过这个循环会改变
				otop--;//出栈
				switch(r){
					case '&':num[ntop-2]=num[ntop-1]&num[ntop-2];ntop--;break;
					case '|':num[ntop-2]=num[ntop-1]|num[ntop-2];ntop--;break;
					case '!':num[ntop-1]=1-num[ntop-1];break;	
				} 
				res=cmp(op[otop-1],c);
			} 
			if(res=='=')otop--;//两个操作符抵消,表达式的继续向前遍历
			if(res=='<')op[otop++]=s[i];
		}
	}
	if(num[0]==0)cout<<"F"<<endl;
	else cout<<"V"<<endl;
}
int main(){
	mp['|']=0;mp['&']=1;mp['!']=2;mp['(']=3;mp[')']=4;mp['#']=5;
	string str;
	while(getline(cin,str)){//cin.getline(s,len)字符数组 
		string s=removespace(str);
		s+='#'; 
		solve(s);
	}
return 0;
}

优先级打表

碰到运算数可以直接输出 一开始在表达式中遇到的运算符都不能轻易去进行运算(考虑到运算符的优先级,后面可能存在优先级比我高的),而是依次保存在栈中,直到继续遍历表达式,遇到了优先级小于操作符栈顶元素的运算符,于是将操作符中操作符出栈进行运算,直到栈顶操作符优先级小于该遇到的操作符,将该操作符入栈

特别的:
铭记是个比较无敌的存在,但是当 遍历表达式遇到的±*/&|与操作符栈顶的
一个铁律:操作符栈中操作符的优先级 大于 表达式后来遇到的操作符才能出栈

1、对于左括号,遍历表达式遇到左括号,优先级一定大于操作符栈顶元素
(相比,(的优先级又是最小的,表达式遇到的操作符入栈

2、不久后少不了),括号里的都处理完了,栈顶元素一个一个弹出直到(,
也就是)的优先级最小

3、栈顶元素和表达式遇到的操作符优先级相同,则算栈顶的优先级更大,因为
先遇到他
4、优先级相等的情况就直接出栈,而表达式当即遇到的操作符也是不能进行
任何操作的(除了入栈,接着就是往后遍历,so优先级相等相当于两个
符号碰撞抵消,有!!,(),##