poj 3295 构造

题意:本题是二叉树的先根遍历,可采用堆栈或递归。给出一个式子,判断是否是永真式,命题有p,q,r,s,t五种,逻辑谓词有K(&),A(|),N(~),C(包含),E(==)五种,我自己是这么理解的用词可能不准确。

思路:构造一个栈,c++现成有,从右往左读输入的字符串,把命题所对应的数据(已经事先生成了,是这些命题的全排列,所有情况组合情况都考虑)压入栈中,每次遇到一个谓词时就取出数据计算,结果再入栈共后边使用。

我这是看的别人写的比较好的代码,我写了注释,转自:http://www.cnblogs.com/yongze103/archive/2010/08/03/1791612.html

3295Accepted208K16MSC++2232B

#include <iostream>
#include <string>
#include <stack>
#include <cstdio>
#include <cstring>
using namespace std;

stack <bool> sta;
bool val[5], flag;

int main() {
	//freopen("poj3295.in", "r", stdin);
	int i, j;
	string str;
	bool tmp1, tmp2;
	while(cin >> str && str != "0")
	{
		flag = 1;
		for(i = 0; i<32 && flag; ++i)//i从0-31(00000-11111)
		{
			memset(val, 0, sizeof(val));
			for(j = 0; j<5; ++j)//j从0-4
			{
				if(i & (1<<j))//(1 << j)的值 分别为10000、01000、00100、00010、00001,下接
					val[j] = 1;//和i取“&”后得分贝可以得出p q r s t全排列的每一种情况。建议自己在纸上枚举一下。
			}
			for(j = str.length() -1; j>=0; --j)
			{
				switch(str[j])
				{
				case 'p': case 'q': case 'r': case 's': case 't':
					sta.push(val[str[j] - 'p']); break;//事先把每个数据压入栈,使用的时候再取。
				case 'N':
					tmp1 = sta.top();
					sta.pop();
					sta.push(!tmp1);
					break;
				case 'E':
					tmp1 = sta.top();
					sta.pop();
					tmp2 = sta.top();
					sta.pop();
					sta.push(tmp1 == tmp2);
				case 'A':
					tmp1 = sta.top();
					sta.pop();
					tmp2 = sta.top();
					sta.pop();
					sta.push(tmp1 || tmp2);
					break;
				case 'K':
					tmp1 = sta.top();
					sta.pop();
					tmp2 = sta.top();
					sta.pop();
					sta.push(tmp1 && tmp2);
					break;
				case 'C':
					tmp1 = sta.top();
					sta.pop();
					tmp2 = sta.top();
					sta.pop();
					if(tmp2 && !tmp1)
						tmp1 = 0;
					else
						tmp1 = 1;
					sta.push(tmp1);
					break;
				default:
					break;
				}
			}
			if(!sta.top()) flag = 0;//针对每种情况,如果计算后的结果为0,就不是永真式
		}
		if(flag) cout << "tautology" << endl;
		else cout << "not" << endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值