题目链接:http://poj.org/problem?id=3295
题目大意:一个逻辑表达式,最多有五个输入人,p,q,r,s,t。有五种操作,判断是不是对于任意输入输出都为1.
解题思路:应为输入只有5个,且输入只能为0,1。所以最多就只有32种情况,有表达式最多100个字符也不多。直接暴力求解即可。用堆栈求解表达式,从表达式从最后开始,如果是p,q,r,s,t压入堆栈,如果是K、A、N、C、E则从堆栈取出操作符需要的数字(除N取1个以外,其它均取2个),进行计算并将结果压入堆栈。
操作符解释:
K --> and: x && y
A --> or: x || y
N --> not : !x
C --> implies : (!x)||y
E --> equals : x==y
#include <cstdio>
#include <cstring>
#include <cassert>
#include <stack>
char data[105];
int x[5];
int len;
using namespace std;
void assign(int n)
{
for (int i = 0; i < 5; ++i)
x[i] = (n >> i) & 1;
}
int getInt(int pos)
{
assert (data[pos]>='p' && data[pos] <='t');
return x[data[pos]-'p'];
}
int caculate ()
{
stack<int> s;
int a, b;
for (int i = len - 1; i >= 0; --i)
{
if (data[i] >= 'p' && data[i] <= 't')
{
s.push(getInt(i));
continue;
}
switch (data[i])
{
case 'N':
a = s.top();s.pop();s.push(1-a);break;
case 'K':
a = s.top();s.pop();b = s.top();s.pop();s.push(a&b);break;
case 'A':
a = s.top();s.pop();b = s.top();s.pop();s.push(a|b);break;
case 'C':
a = s.top();s.pop();b = s.top();s.pop();s.push((!a)|b);break;
case 'E':
a = s.top();s.pop();b = s.top();s.pop();s.push(a==b);break;
}
}
return s.top();
}
int main ()
{
while (scanf ("%s", data))
{
if (data[0] == '0')
break;
len = strlen(data);
int i;
for (i = 0; i < 32; ++i)
{
assign(i);
if(caculate () == 0)
break;
}
if (i == 32)
printf ("tautology\n");
else
printf ("not\n");
}
return 0;
}