码迷,mamicode.com
首页 > 其他好文 > 详细

构造法 poj3295

时间:2014-08-28 16:50:50      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   os   使用   io   strong   

Tautology
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9580   Accepted: 3640

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.
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 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

这道题的意思:用字符串的形式给你一个逻辑表达式,判断是否为永真式,逻辑变量只有那五个小写字母

这是我的代码,没什么价值

bubuko.com,布布扣
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const char ch[5]={p,q,r,s,t};
char a[120];
int rep[255];
 int f[120];
int len;
void printrep(){
    for(int i=0;i<5;i++){
        printf("%c%d ",ch[i],rep[ch[i]]);
    }
    puts("");
}
bool isnum(char ch1){
    for(int i=0;i<5;i++)if(ch1==ch[i])return true;
    return false;
}
bool dfs(int ind){
    if(ind<5){if(!dfs(ind+1))return false;rep[ch[ind]]=1;if(!dfs(ind+1))return false;rep[ch[ind]]=0;return true;}
    memset(f,0,sizeof(f));
    int index=0;
    for(int i=len-1;i>=0;i--){
        if(isnum(a[i])){
            f[index++]=rep[a[i]];
        }
        else {
            if(a[i]==K){
                f[index-2]=f[index-2]&f[index-1];
                index--;
            }
            if(a[i]==A){
                  f[index-2]=f[index-2]|f[index-1];
                index--;
            }
            if(a[i]==N){
                f[index-1]=1^f[index-1];
            }
            if(a[i]==C){
                f[index-2]=((1^f[index-1])|f[index-2]);
                index--;
            }
            if(a[i]==E){
                f[index-2]=1^(f[index-2]^f[index-1]);
                index--;
            }
        }
    }
    if(f[index-1]==0)return false;
    return true;
}
int main()
{
    while(scanf("%s",a)==1&&strcmp(a,"0")){
        memset(rep,0,sizeof(rep));
        len=strlen(a);
        if(dfs(0)){
            puts("tautology");
        }
        else {
            puts("not");
        }
    }
    return 0;
}
View Code
int ind()//这位大神这么做的看起来清洁干净   
{
    char ch=s[l++];//把整个堆栈过程和变量分开看了
    printf("");
    
    switch(ch)
    {
    case p:
    case q:
    case r:
    case s:
    case t:
        return state[ch];
        break;
    case K:
        return ind()&ind();       
        break;
    case A:
        return ind()|ind();
        break;
    case N:
        return !ind();
        break;
    case C:
        return !ind()|ind();
        break;
    case E:
        return ind()==ind();
        break;
    }
}

还可以字符替换,不贴了,可以增强直观,反正数据不大

讨论区看到的

WA来自那些递归下降求解的代码.
第一种情况,使用|| 和 &&:
例如s为所给串
int getval()
{
	switch(s[c_s++])
	{
	case ‘p‘: return (value & (1 << 0))? 1:0;
	case ‘q‘: return (value & (1 << 1))? 1:0;
	case ‘r‘: return (value & (1 << 2))? 1:0;
	case ‘s‘: return (value & (1 << 3))? 1:0;
	case ‘t‘: return (value & (1 << 4))? 1:0;

	case ‘K‘: return getval() && getval();
	case ‘A‘: return getval() || getval();
	case ‘N‘: return !getval();
	case ‘C‘: return !getval() || getval();
	case ‘E‘: return getval() == getval();
	}
}
这种情况简单,大家知道短路求值吧,先对 ||左边的表达式求值,如果非0,则不会对右边的表达式求值,&&同理,如果左边为0,不会对右边求值,这样下标就不会按照事先设想的增加
第二种情况,使用&和|:
int getval()
{
	switch(s[c_s++])
	{
	case ‘p‘: return (value & (1 << 0))? 1:0;
	case ‘q‘: return (value & (1 << 1))? 1:0;
	case ‘r‘: return (value & (1 << 2))? 1:0;
	case ‘s‘: return (value & (1 << 3))? 1:0;
	case ‘t‘: return (value & (1 << 4))? 1:0;

	case ‘K‘: return getval() & getval();
	case ‘A‘: return getval() | getval();
	case ‘N‘: return !getval();
	case ‘C‘: return !getval() | getval();
	case ‘E‘: return getval() == getval();
	}
}
首先这段代码用G++会AC,C++会WA,说明此段代码依赖编译器,是未定义的代码
错误原因: C语言对表达式的求值顺序不是明确规定的,而G++是从左从左向右求值,C++则正好相反,比如: getval() | getval() G++先对左边的getval()求值,而C++则先对右边的getval()求值,也就会导致对s的访问顺序不会按预先的步骤进行,所以用G++会ac,C++会WA掉
正确的写法,去掉那些跟依赖求值顺序的代码(好习惯),分别求值,用两个临时变量保存,这样G++和C++都AC了:
int getval()
{       int temp1, temp2;
	switch(s[c_s++])
	{
	case ‘p‘: return (value & (1 << 0))? 1:0;
	case ‘q‘: return (value & (1 << 1))? 1:0;
	case ‘r‘: return (value & (1 << 2))? 1:0;
	case ‘s‘: return (value & (1 << 3))? 1:0;
	case ‘t‘: return (value & (1 << 4))? 1:0;

	case ‘K‘: temp1 = getval(); temp2 = getval(); return temp1 & temp2;
	case ‘A‘: temp1 = getval(); temp2 = getval(); return temp1 | temp2;
	case ‘N‘: return !getval();
	case ‘C‘: temp1  = !getval(); temp2 = getval(); return temp1 | temp2;
	case ‘E‘: temp1 = getval(); temp2 = getval(); return temp1 == temp2;
	}
}

构造法 poj3295

标签:des   style   blog   http   color   os   使用   io   strong   

原文地址:http://www.cnblogs.com/xuesu/p/3941895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!