POJ 3295: Tautology

题目来源:http://poj.org/problem?id=3295

Tautology

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 14016

Accepted: 5414

Description

WFF 'N PROOF is a logic game played with dice. Each die has sixfaces 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 thefollowing 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

tautology is a WFF that has value 1 (true)regardless of the values of its variables. For example, ApNp isa tautology because it is true regardless of the value of p. On theother 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 singleline containing a WFF with no more than 100 symbols. A line containing 0follows the last case.

Output

For each test case, output a line containing tautology or not asappropriate.

Sample Input

ApNp
ApNq
0

SampleOutput

tautology
not

Source

Waterloo Local Contest,2006.9.30

-----------------------------------------------------

解题思路

由于每个表达式最多只有5个变量:p,q,r,s,t. 所以每个表达式最多只有32种取值,遍历即可。

前缀表达式(波兰表达式)用递归计算,可参看NOI 2.2 递归 1696: 逆波兰表达式

注意:&&和||有“短路”现象,即若左式=false, &&不会计算右式; 若左式=true, ||不会计算右式。

-----------------------------------------------------

代码

#include<fstream>
#include<iostream>
#include<string>
#include<set>
using namespace std;

string s;
int mycount = 0;

bool compute(const set<char> &pqrst, int j)			// 递归法解前缀表达式
{
	char ch = s.at(mycount++);
	int mycnt = 0 ,index = 0;
	set<char>::iterator it;
	bool left,right;
	switch(ch)
	{
	case 'K': 
		left = compute(pqrst, j);	// &&,||有短路现象,即若左式=false,&&不会计右式;若左式=true,||不会计算右式
		right = compute(pqrst, j);
		return left&&right;
		break;
	case 'A': 
		left = compute(pqrst, j);
		right = compute(pqrst, j);
		return left||right;
		break;
	case 'N': 
		left = compute(pqrst, j);
		return !left;
		break;
	case 'C': 
		left = compute(pqrst, j);
		right = compute(pqrst, j);
		return left<=right;
		break;
	case 'E': 
		left = compute(pqrst, j);
		right = compute(pqrst, j);
		return left==right;
		break;
	default: 
		for (it=pqrst.begin(); it!=pqrst.end(); it++)	// 根据遍历计数器计算每个符号代表的值
		{
			if (ch==*it)
			{
				index = mycnt;
				break;
			}
			mycnt++;
		}
		return (j>>index)%2;
		break;
	}
}


int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin("3295.txt");
	int i = 0, cnt = 0, num = 0, j;
	char c;
	set<char> pqrst;
	bool is = true;
	while (fin >> s)
	{
		if (s=="0")
		{
			break;
		}
		pqrst.clear();
		is = true;
		for (i=0; i<s.size(); i++)
		{
			c = s.at(i);
			if (c=='p' || c=='q' || c=='r' || c=='s' || c=='t')
			{
				pqrst.insert(c);
			}
		}
		cnt = pqrst.size();
		num = 1<<cnt;
		for (j=0; j<num; j++)
		{
			mycount = 0;
			is = compute(pqrst,j);
			if (!is)
			{
				break;
			}
		}
		if (!is)
		{
			cout << "not" << endl;
		}
		else
		{
			cout << "tautology" << endl;
		}
	}
	fin.close();
#endif
#ifdef ONLINE_JUDGE
	int i = 0, cnt = 0, num = 0, j;
	char c;
	set<char> pqrst;
	bool is = true;
	while (cin >> s)
	{
		if (s=="0")
		{
			break;
		}
		pqrst.clear();
		is = true;
		for (i=0; i<s.size(); i++)
		{
			c = s.at(i);
			if (c=='p' || c=='q' || c=='r' || c=='s' || c=='t')
			{
				pqrst.insert(c);
			}
		}
		cnt = pqrst.size();
		num = 1<<cnt;
		for (j=0; j<num; j++)
		{
			mycount = 0;
			is = compute(pqrst,j);
			if (!is)
			{
				break;
			}
		}
		if (!is)
		{
			cout << "not" << endl;
		}
		else
		{
			cout << "tautology" << endl;
		}
	}
#endif
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值