Tautology
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9580 | Accepted: 3640 |
Description
WFF ‘N PROOF is a logic game played with dice. Each die has six faces representing some subset of the possible symbols K, A, N, C, E, p, q, r, s, t. A Well-formed formula (WFF) is any string of these symbols obeying the following rules:
- p, q, r, s, and t are WFFs
- if w is a WFF, Nw is a WFF
- if w and x are WFFs, Kwx, Awx, Cwx, and Ewx are WFFs.
The meaning of a WFF is defined as follows:
- p, q, r, s, and t are logical variables that may take on the value 0 (false) or 1 (true).
- K, A, N, C, E mean and, or, not, implies, and equals as defined in the truth table below.
Definitions of K, A, N, C, and E |
w x | Kwx | Awx | Nw | Cwx | Ewx |
1 1 | 1 | 1 | 0 | 1 | 1 |
1 0 | 0 | 1 | 0 | 0 | 0 |
0 1 | 0 | 1 | 1 | 1 | 0 |
0 0 | 0 | 0 | 1 | 1 | 1 |
A tautology is a WFF that has value 1 (true) regardless of the values of its variables. For example, ApNp is a tautology because it is true regardless of the value of p. On the other hand, ApNq is not, because it has the value 0 for p=0, q=1.
You must determine whether or not a WFF is a tautology.
Input
Input consists of several test cases. Each test case is a single line containing a WFF with no more than 100 symbols. A line containing 0 follows the last case.
Output
For each test case, output a line containing tautology or not as appropriate.
Sample Input
ApNp ApNq 0
Sample Output
tautology not
这道题的意思:用字符串的形式给你一个逻辑表达式,判断是否为永真式,逻辑变量只有那五个小写字母
这是我的代码,没什么价值
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const char ch[5]={‘p‘,‘q‘,‘r‘,‘s‘,‘t‘}; char a[120]; int rep[255]; int f[120]; int len; void printrep(){ for(int i=0;i<5;i++){ printf("%c%d ",ch[i],rep[ch[i]]); } puts(""); } bool isnum(char ch1){ for(int i=0;i<5;i++)if(ch1==ch[i])return true; return false; } bool dfs(int ind){ if(ind<5){if(!dfs(ind+1))return false;rep[ch[ind]]=1;if(!dfs(ind+1))return false;rep[ch[ind]]=0;return true;} memset(f,0,sizeof(f)); int index=0; for(int i=len-1;i>=0;i--){ if(isnum(a[i])){ f[index++]=rep[a[i]]; } else { if(a[i]==‘K‘){ f[index-2]=f[index-2]&f[index-1]; index--; } if(a[i]==‘A‘){ f[index-2]=f[index-2]|f[index-1]; index--; } if(a[i]==‘N‘){ f[index-1]=1^f[index-1]; } if(a[i]==‘C‘){ f[index-2]=((1^f[index-1])|f[index-2]); index--; } if(a[i]==‘E‘){ f[index-2]=1^(f[index-2]^f[index-1]); index--; } } } if(f[index-1]==0)return false; return true; } int main() { while(scanf("%s",a)==1&&strcmp(a,"0")){ memset(rep,0,sizeof(rep)); len=strlen(a); if(dfs(0)){ puts("tautology"); } else { puts("not"); } } return 0; }
int ind()//这位大神这么做的看起来清洁干净 { char ch=s[l++];//把整个堆栈过程和变量分开看了 printf(""); switch(ch) { case ‘p‘: case ‘q‘: case ‘r‘: case ‘s‘: case ‘t‘: return state[ch]; break; case ‘K‘: return ind()&ind(); break; case ‘A‘: return ind()|ind(); break; case ‘N‘: return !ind(); break; case ‘C‘: return !ind()|ind(); break; case ‘E‘: return ind()==ind(); break; } }
还可以字符替换,不贴了,可以增强直观,反正数据不大
讨论区看到的
WA来自那些递归下降求解的代码. 第一种情况,使用|| 和 &&: 例如s为所给串 int getval() { switch(s[c_s++]) { case ‘p‘: return (value & (1 << 0))? 1:0; case ‘q‘: return (value & (1 << 1))? 1:0; case ‘r‘: return (value & (1 << 2))? 1:0; case ‘s‘: return (value & (1 << 3))? 1:0; case ‘t‘: return (value & (1 << 4))? 1:0; case ‘K‘: return getval() && getval(); case ‘A‘: return getval() || getval(); case ‘N‘: return !getval(); case ‘C‘: return !getval() || getval(); case ‘E‘: return getval() == getval(); } } 这种情况简单,大家知道短路求值吧,先对 ||左边的表达式求值,如果非0,则不会对右边的表达式求值,&&同理,如果左边为0,不会对右边求值,这样下标就不会按照事先设想的增加 第二种情况,使用&和|: int getval() { switch(s[c_s++]) { case ‘p‘: return (value & (1 << 0))? 1:0; case ‘q‘: return (value & (1 << 1))? 1:0; case ‘r‘: return (value & (1 << 2))? 1:0; case ‘s‘: return (value & (1 << 3))? 1:0; case ‘t‘: return (value & (1 << 4))? 1:0; case ‘K‘: return getval() & getval(); case ‘A‘: return getval() | getval(); case ‘N‘: return !getval(); case ‘C‘: return !getval() | getval(); case ‘E‘: return getval() == getval(); } } 首先这段代码用G++会AC,C++会WA,说明此段代码依赖编译器,是未定义的代码 错误原因: C语言对表达式的求值顺序不是明确规定的,而G++是从左从左向右求值,C++则正好相反,比如: getval() | getval() G++先对左边的getval()求值,而C++则先对右边的getval()求值,也就会导致对s的访问顺序不会按预先的步骤进行,所以用G++会ac,C++会WA掉 正确的写法,去掉那些跟依赖求值顺序的代码(好习惯),分别求值,用两个临时变量保存,这样G++和C++都AC了: int getval() { int temp1, temp2; switch(s[c_s++]) { case ‘p‘: return (value & (1 << 0))? 1:0; case ‘q‘: return (value & (1 << 1))? 1:0; case ‘r‘: return (value & (1 << 2))? 1:0; case ‘s‘: return (value & (1 << 3))? 1:0; case ‘t‘: return (value & (1 << 4))? 1:0; case ‘K‘: temp1 = getval(); temp2 = getval(); return temp1 & temp2; case ‘A‘: temp1 = getval(); temp2 = getval(); return temp1 | temp2; case ‘N‘: return !getval(); case ‘C‘: temp1 = !getval(); temp2 = getval(); return temp1 | temp2; case ‘E‘: temp1 = getval(); temp2 = getval(); return temp1 == temp2; } }