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 205
char 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 ;
else
return 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 ;
}
}
else
i++ ;
}
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 ;
}