Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12088 | Accepted: 4608 |
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.
- 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.
|
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
这是一道构造法的题目,说白了就是自己构造了一些判断符号,比如K其实就是 && ,A就是 || ,N就是 !, C和E的话没有现成的,要自己去判断。
这道题目就是说给定了一个字符串,然后让你去判断,当中的变量只能是0或者1,如果有一种情况导致这个语句输出为0,那么就输出not,如果任何情况都不会为0,那就输出tautology。
本来我一直怀疑,这字符串最多可以长到100,如果是一堆的N之类的,变量如果有很多,30多个,都是不一样的,那么就有2的30次方种情况,肯定会T。我就一直想到底怎么写好,后来看了看题目,发现只有五个变量p,q,r,s,t。这最多也就2的五次方也就是32种情况,瞎暴力一通都能过的。
然后就是想法问题了,一开始我用栈stack直接遍历一遍把操作符和变量分别装到两个栈中,但是有一个很棘手的问题,那就是,你每次都要把这个语句给复制一遍啊,栈并不好复制出去,因为都是要一个一个出去的,要复制最后还是要归根到数组,所以想到了直接每次用数组来读。
不需要操作符栈,只需要数字栈,我直接从数组最后面开始读,读到KACE,就直接在数字栈中取出两个数字,判断,再放进数字栈中一个数字。如果是读到N,那么就在数字栈中取出一个数字,然后判断后放回数字栈中。如果读到变量名字,那就直接在map中读出这个字符对应的数字,放进数字栈中。
代码如下:
#include<cstdio>
#include<stack>
#include<set>
#include<map>
#include<iostream>
#include<cstring>
using namespace std;
map<char, int>Map;
int k1, k2, len;
char str[105];
int func()
{
stack<int> t_num;
char ch;
int tmp1, tmp2;
for(int i = len - 1; i >= 0; i--)
if(str[i] == 'K' || str[i] == 'A' || str[i] == 'C' || str[i] == 'E')
{
tmp1 = t_num.top();
t_num.pop();
tmp2 = t_num.top();
t_num.pop();
if(str[i] == 'K')
t_num.push(tmp1 && tmp2);
else if(str[i] == 'A')
t_num.push(tmp1 || tmp2);
else if(str[i] == 'C')
{
if(tmp1 == 0 && tmp2 == 1)
t_num.push(0);
else
t_num.push(1);
}
else if(str[i] == 'E')
{
if(tmp1 == tmp2)
t_num.push(1);
else
t_num.push(0);
}
}
else if(str[i] == 'N')
{
tmp1 = t_num.top();
t_num.pop();
t_num.push(!tmp1);
}
else
t_num.push(Map[str[i]]);
tmp1 = t_num.top();
while(!t_num.empty())
t_num.pop();
return tmp1;
}
int main()
{
int flag;
while(scanf("%s",str), str[0] != '0')
{
len = strlen(str);
k1 = k2 = 0;
flag = 1;
for(int p = 0; p < 2 && flag; p++)
{
Map['p'] = p;
for(int q = 0; q < 2 && flag; q++)
{
Map['q'] = q;
for(int r = 0; r < 2 && flag; r++)
{
Map['r'] = r;
for(int s = 0; s < 2 && flag; s++)
{
Map['s'] = s;
for(int t = 0; t < 2 && flag; t++)
{
Map['t'] = t;
if(func() == 0)
flag = 0;
}
}
}
}
}
if(flag)
printf("tautology\n");
else
printf("not\n");
}
return 0;
}
经过了这一道题目,我确实加深了C语言对运算符操作的方法,原来是这么的奇妙,一开始我真的写不出来的,因为我都是想从前往后遍历输入语句。
但是我觉得其实从前往后遍历也是可以的,但是想了想我觉得挺复杂的,比如CCCC100这种,我就需要一个运算栈来存放C,一直放,放到他读到数字为止,如果有N,比如CCCN100,那么读到N后自动读入后面一个数字判断然后放进去数字栈,写起来感觉还是很麻烦,还是从后往前遍历好了,就这么定了23333。