首页 > 代码库 > 构造法 poj3295

构造法 poj3295

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

ApNpApNq0

Sample Output

tautologynot

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

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

#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