Tautology
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:
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
Source
总结:
递归题,表达式,永真式
做了两个版本
WA了很多次,原来是把题目意思看错了。开始理解为不管任何pqrst值,计算结果都一样的是tautology。
AC代码1
#include <iostream> #include <string> #include <cctype> using namespace std; int p, q, r, s, t; int K[2][2]={0, 0, 0, 1}, A[2][2]={0, 1, 1, 1}, N[2]={1, 0}, C[2][2]={1, 1, 0, 1}, E[2][2]={1, 0, 0, 1}; int getv(char ch) { switch (ch) { case (int)'p': return p; case (int)'q': return q; case (int)'r': return r; case (int)'s': return s; case (int)'t': return t; } } int dfs(string str, int& len) { int a, b, ret, len1=0, len2=0; if (isupper(str[1])) a=dfs( str.substr(1), len1); else { a=getv(str[1]); len1=1; } if (str[0]!='N') { if (isupper(str[len1+1])) b=dfs( str.substr(len1+1), len2 ); else { b=getv(str[len1+1]); len2=1; } } len=1+len1+len2; switch(str[0]) { case (int)'K': ret=K[a][b]; break; case (int)'A': ret=A[a][b]; break; case (int)'N': ret=N[a]; break; case (int)'C': ret=C[a][b]; break; case (int)'E': ret=E[a][b]; break; } return ret; } int main() { string str; while (cin >> str && str!="0") { p=0, q=0, r=0, s=0, t=0; int len=0; bool done=false; for (p=0;p<=1 && !done;p++) for (q=0;q<=1 && !done; q++) for (r=0;r<=1 && !done; r++) for (s=0;s<=1 && !done; s++) for (t=0;t<=1 && !done; t++) if (dfs(str, len)!=1) done=true; if (done) cout << "not/n"; else cout << "tautology/n"; } return 0; }
后来看了discuss的提示,给出了另一个很精简的写法
AC代码2
#include <iostream> #include <string> using namespace std; int p, q, r, s, t; int K[2][2]={0, 0, 0, 1}, A[2][2]={0, 1, 1, 1}, N[2]={1, 0}, C[2][2]={1, 1, 0, 1}, E[2][2]={1, 0, 0, 1}; string str; int now; int calc() { now++; switch(str[now]) { case (int)'K':return calc() & calc(); case (int)'A':return calc() | calc(); case (int)'N':return !calc(); case (int)'C':return C[calc()][calc()]; case (int)'E':return E[calc()][calc()]; case (int)'p':return p; case (int)'q':return q; case (int)'r':return r; case (int)'s':return s; case (int)'t':return t; } } int main() { while (cin >> str && str!="0") { bool done=false; for (p=0;p<=1 && !done;p++) for (q=0;q<=1 && !done; q++) for (r=0;r<=1 && !done; r++) for (s=0;s<=1 && !done; s++) for (t=0;t<=1 && !done; t++) { now=-1; if (calc()!=1) done=true; } if (done) cout << "not/n"; else cout << "tautology/n"; } return 0; }
在网上,还发现一个用位运算的更精简的写法,学习了。
http://www.cnblogs.com/asuran/archive/2009/09/28/1575379.html
// POJ3295.cpp : Defines the entry point for the console application. // #include <iostream> #include <string> using namespace std; static int pos = -1; bool WFF(const string& formula, int i) { ++pos; switch(formula[pos]) { case 'p': return i & 1; case 'q': return (i >> 1) & 1; case 'r': return (i >> 2) & 1; case 's': return (i >> 3) & 1; case 't': return (i >> 4) & 1; case 'N': return !WFF(formula, i); case 'K': return WFF(formula, i) & WFF(formula, i); case 'A': return WFF(formula, i) | WFF(formula, i); case 'C': return !WFF(formula, i) | WFF(formula, i); case 'E': return WFF(formula, i) == WFF(formula, i); } return false; }; bool isTautology(string formula) { for (int i = 0; i < 32; ++i) { pos = -1; if (WFF(formula, i)==false) return false;; } return true; }; int main(int argc, char* argv[]) { string ln; while (cin >> ln && ln[0] != '0') { if (isTautology(ln)) cout << "tautology/n"; else cout << "not/n"; } return 0; }