ZOJ_3585 Equivalent Expression 表达式求值

来源:互联网 发布:centos ftp 编辑:程序博客网 时间:2024/05/16 09:48

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3585

题意:给两个真值表达式,判断两者是否等价,两个表达式等价是指:对于表达式内的所有变量的任意指定,两个表达式的真值都一样。已知表达式内的变量的个数最多为15个。

思路:因为任一表达式内的变量的个数最多为15个,枚举所有的情况一共有2^15=32768种情况,这里我们可以用一个dfs实现真值的   指派。接着指定了表达式内变量的真值以后, 就是一个表达式的求值问题了,这里一共给了6种运算符: !、&、|、^、(、)。而且给出了运算符的优先级:!>&>|>^ ,所以接下来的任务就是在O(n)的时间内将表达式的值求出,并每次都比较两个表达式在特定的指派下的值,若有一次两者不相等就可以break出来了。求表达式值的时候,用两个栈分别存放运算符和运算数,每次判断两个运算符的优先级,并执行相应的操作。

代码:

#include<stdio.h>#include<string.h>#include<ctype.h>#define MAXN 205char s1[MAXN],s2[MAXN] ;int len1 ,len2 ,cnt;char name[16][12] ;bool val[16] ;char optr[202] ; bool opnd[202] ;int top1,top2 ;void push1(char c){optr[top1++] = c ;}char pop1(){top1-- ;return optr[top1] ;}void push2(bool v){opnd[top2++] = v ;}bool pop2(){top2-- ;return opnd[top2] ;}int find(char *p){for(int i=0;i<cnt;i++){if(strcmp(p,name[i]) == 0)return i ;}return -1 ;}bool is_ope(char c){if(c=='&' || c=='|' || c=='!' || c=='^' || c=='(' || c==')' || c=='#')return true ;elsereturn false ;}int GetPriority(char a,char b){//判断优先级 int r ;//0 : 出栈  1 :计算 -1 : 入栈  switch(b){case '!' :r = -1 ;break ;case '&' :if(a=='!' || a==')'){r = 1 ;}else r = -1 ;break ;case '|' :if(a=='!' || a=='&' ||a==')'){r = 1 ;}else r = -1 ;break ;case '^' :if(a=='!' || a=='&' || a=='|' ||a==')'){r = 1 ;}else r = -1 ;break ;case '(' :r = -1 ;break ;case ')' :if(a=='(')r = 0 ;else r = 1 ;break ;  case '#' :if(a=='#')r = 0 ;else r = 1 ;break ;}return r ;}bool calculate(bool a, bool b, char ope){switch(ope){case '&' :return a & b ;case '|' :return a | b ;case '^' :return a ^ b ;}}bool solve(char s[],int len){top1 = top2 = 0 ;push1('#') ;int i, j ,n;bool a1,a2 ;i = 0 ;char str[20],c,ss;j = 0 ;while(i <= len){while(isalpha( s[i] )){str[j++] = s[i] ;i++ ;}if(j!=0){str[j] = 0 ;n = find( str );push2( val[n] );j = 0 ;}if( is_ope(s[i]) ){c = s[i] ;ss = optr[top1 - 1] ;switch( GetPriority(ss,c) ){case 0 :pop1();i++ ;break ;case -1:push1(c) ;i ++ ;break ;case 1 :if(ss == '!'){a1 = pop2() ;ss = pop1() ;push2( !a1 );}else{a1 = pop2() ;a2 = pop2() ;ss = pop1() ;push2( calculate(a2,a1,ss) );}break ;}}elsei++ ;}return opnd[top2-1] ;}bool check(){if(solve(s1,len1) != solve(s2,len2))return false ;return true ;}bool dfs(int pos){//指定真值 if(pos == cnt){int i , j ;i = 1 ;return check() ;}if(!dfs(pos+1))return false ;val[pos] = 1 ;if(!dfs(pos+1))return false ;val[pos] = 0 ;return true ;}int main(){int n ;char str[20] ;while(gets(s1) && s1[0]){gets(s2) ;cnt = 0 ;len1 = strlen(s1);len2 = strlen(s2); s1[len1] = '#' ;s2[len2] = '#' ;bool ok = 0 ;int c = 0 ;for(int i=0;i<len1;i++){if(isalpha( s1[i] )){str[c++] = s1[i] ;ok = 1 ;continue ;}else {if( ok ){str[c] = 0 ;n = find(str);if( n==-1 ){strcpy(name[cnt] , str);cnt++ ;}ok = 0 ; c = 0  ;}}}if(ok){n = find(str);if( n==-1 ){strcpy(name[cnt] , str);cnt++ ;}}memset( val,0,sizeof(val) );if(!dfs(0)){printf("FALSE\n");}else printf("TRUE\n");}return 0 ;}


原创粉丝点击