消解算法

成绩 100 开启时间 2017年04月6日 星期四 08:00
折扣 0.8 折扣时间 2017年05月5日 星期五 08:00
允许迟交 关闭时间 2017年05月18日 星期四 23:55

实现功能:消解算法

输入:合式公式 A 的合取范式

输出:当 A 是可满足时,回答“YES ”;否则回答“NO”。

输入公式的符号说明:

! 非,相当于书面符号中的 “ ¬ ”

& 与,相当于书面符号中的 “ ∧ ”

| 或,相当于书面符号中的 “ ∨ ”

- 蕴含联结词,相当于书面符号中的 “ → ”

+ 等价联结词,相当于书面符号中的 “ ↔ ”

( 前括号

) 后括号

  测试输入关于“测试输入”的帮助 期待的输出关于“期待的输出”的帮助 时间限制关于“时间限制”的帮助 内存限制关于“内存限制”的帮助 额外进程关于“{$a} 个额外进程”的帮助
测试用例 1 以文本方式显示
  1. (!p|q)&(p|q)&(!q)↵
以文本方式显示
  1. NO↵
无限制 64M 0
测试用例 2 以文本方式显示
  1. p&(p|q)&(p|!q)&(q|!r)&(q|r)↵
以文本方式显示
  1. YES↵
无限制 64M 0

#include<stdio.h> 
#include<stdlib.h> 
#include<math.h> 
#include<string.h> 
#define N 100 
int s[30][30]; 
//每行存储一个简单析取式,第二维下标0~25代表命题变项a~z 
//取值 0: 该变项没有出现,1: 该变项出现,2: 该变项出现且为否定 
int s0,s1,s2;//实现对集合0,集合1,集合2 的指向 
void save(char str[]);//将输入字符串存到s数组,标记到集合2 
int i_same(int a[],int b[]); 
int check(int c[]); 
int res(int a[],int b[]); 
int main() 
{int i,j; 
 char str[N]; 
 scanf("%s",str); 
 save(str);  
 do{ 
    s0=s1;s1=s2;//将集合1并到集合0中,令集合1等于集合2,清空集合2 
    for(i=0;i<=s0;i++) 
  for(j=s0+1;j<=s1;j++) 
    { 
        if(!res(s[i],s[j])) 
        {printf("NO\n"); 
       return 0;} 
   } 
      for(i=s0+1;i<=s1;i++) 
   for(j=i+1;j<=s1;j++) 
    { 
      if(!res(s[i],s[j])) 
    {printf("NO\n"); 
   return 0;} 
      } 
      
     } while(s2>s1);//若集合2为空,结束 
  printf("YES\n"); 
   return 0; 
} 
void save(char str[]) 
{ 
   int i,j,len=strlen(str); 
   s0=s1=-1;s2=0;   
   for(i=0;i<30;i++)    for(j=0;j<30;j++) s[i][j]=0; 
   
    
   i=0;  
   while(i<len) 
   { 
    if(str[i]>='a'&&str[i]<='z') 
     s[s2][str[i]-'a']=1; 
     else if(str[i]=='&') s2++; 
     else if(str[i]=='!') 
     s[s2][str[++i]-'a']=2; 
     i++; 
   } 
} 
int i_same(int a[],int b[])//判断两简单析取式是否相同 
{ 
 int i; 
 for(i=0;i<26;i++) 
   if(a[i]!=b[i]) 
     return 0; 
  return 1; 
  
} 
int check(int c[])//检查集合0,集合1,集合2中是否有重复 
{ 
    int i; 
 for(i=0;i<=s2;i++) 
  if(i_same(s[i],c)) 
 return 0; 
   
   return 1; 
} 
int res(int a[],int b[])//消解函数,若得到空子句,返回0,否则返回1 
{ 
  int single=0;//不能消解的变项个数 
   int couple=0;//可消解的变项个数 
    int c[30];//消解结果 
   int i; 
 for(i=0;i<26;i++) 
   {    
       if(!a[i]&&!b[i])  continue; 
        if((a[i]==1&&b[i]==2)||(a[i]==2&&b[i]==1)) couple++; 
       else single++; 
 } 
  if(couple!=1) return 1;//不能消解或有多对可以消解 
  if(!single)   return 0;//只有一对可消解且没有不能消解的变项,得到空子句 
    
   for(i=0;i<26;i++) 
   { 
      if((!a[i]&&!b[i])||(a[i]+b[i]==3)) c[i]=0; 
     else if (a[i]==1||b[i]==1) c[i]=1; 
     else c[i]=2; 
   } 
  if(check(c))//检查c在集合0.集合1,集合2中是否出现过 
    { 
      s2++;//将c加入集合2 
     for(i=0;i<26;i++) s[s2][i]=c[i]; 
    } 
  return 1; 
}  


  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值