离散数学—求主范式

来源:互联网 发布:淘宝买到假货已经下架 编辑:程序博客网 时间:2024/06/08 07:47

输入:命题公式的合式公式

输出:公式的主析取范式和主析取范式,输出形式为:“ mi ∨ mj ; Mi ∧ Mj” ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用“ ; ”隔开,“ ; ”前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范式为 0 。

输入公式的符号说明:

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

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

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

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

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

( 前括号

) 后括号

方法一:

#include <cstdio>  #include <cstring>  #include <cmath>  #define N 1000  #define MAX 10000000  char s[N];  bool table[30];  //标记出现的字母 int explain[30];  //存放每个字母的值 int value[MAX];  int sum = 0;  int priority(char c)  {      switch (c)      {          case '#': return -1;          case '!': return 5;          case '&': return 4;          case '|': return 3;          case '-': return 2;          case '+': return 1;          case '(': return 0;          default: return 0;      }  }  void postfix()  //将字符串处理 {      char post[N] = { '\0' };      int pp = -1;      char stack[N] = { '#' };      int ps = 0;        int len = strlen(s);      for (int i = 0; i < len; i++)      {          if (s[i] >= 'a' && s[i] <= 'z')          {              post[++pp] = s[i];              continue;          }          if (s[i] == '!' || s[i] == '&' || s[i] == '|' || s[i] == '-' || s[i] == '+')          {              while (priority(s[i]) <= priority(stack[ps]))                  post[++pp] = stack[ps--];              stack[++ps] = s[i];              continue;          }          if (s[i] == '(')          {              stack[++ps] = s[i];              continue;          }          if (s[i] == ')')          {              while (stack[ps] != '(') post[++pp] = stack[ps--];              ps--;              continue;          }      }      while (ps) post[++pp] = stack[ps--];      strcpy(s, post);      int l = strlen(s);  }  void settable()  //统计字母的个数{      memset(table, 0, sizeof(table));      int len = strlen(s);      for (int i = 0; i < len; i++)      {          if (s[i] >= 'a' && s[i] < 'z')              table[s[i] - 'a'] = true;      }      for (int i = 0; i < 26; i++)          if (table[i]) sum++;      sum = pow(2, sum);  }  int btoi()  //将二进制转化为十进制 {      int sum = 0, weight = 1;      for (int i = 25; i >= 0; i--)          if (table[i])          {              if (explain[i]) sum += weight;              weight *= 2;          }      return sum;  }  int calc(int a, int b, char c)  //定义运算 {      switch (c)      {          case '&': return a * b;          case '|': if (a + b) return 1; else return 0;          case '-': if (a == 1 && b == 0) return 0; else return 1;          case '+': return !((a + b) & 1);      }  }  int work()  //判断字符串的真值 {      int stack[N], ps = -1;      int len = strlen(s);      for (int i = 0; i < len; i++)      {          if (s[i] >= 'a' && s[i] <= 'z')          {              stack[++ps] = explain[s[i] - 'a'];              continue;          }          if (s[i] == '!')          {              stack[ps] = (stack[ps] + 1) & 1;              continue;          }          int ans = calc(stack[ps - 1], stack[ps], s[i]);          stack[--ps] = ans;      }      return stack[0];  }  void assign()  {      int x = btoi();      int ans = work();      value[x] = ans;  }  void generate(char c)  //从a开始,用递归对出现的字母进行0,1赋值 {      while (c <= 'z' && table[c - 'a'] == false) c++;      if (c > 'z')      {          assign();          return;      }      explain[c - 'a'] = 0;      generate(c + 1);      explain[c - 'a'] = 1;      generate(c + 1);  }  void output1()  {      int i = 0;      while (i < sum && !value[i]) i++;      if (i >= sum)      {          printf("0 ; ");          return;      }      printf("m%d", i);      for (i++; i < sum; i++)          if (value[i]) printf(" ∨ m%d", i);      printf(" ; ");  }  void output2()  {      int i = 0;      while (i < sum && value[i]) i++;      if (i >= sum)      {          printf("1\n");          return;      }      printf("M%d", i);      for (i++; i < sum; i++)          if (!value[i]) printf(" ∧ M%d", i);      printf("\n");  }  int main()  {      scanf("%s", s);      postfix();      settable();      memset(value, 0, sizeof(value));      memset(explain, 0, sizeof(explain));      generate('a');      output1();      output2();      return 0;  } 


方法二:

#include<cstdio>#include<cstring>#include<cmath>#define N 1000using namespace std; void panduan(int b[N],int f);//赋值函数int tkh (char sz[N], char ccu[N], int icu[N], int h0);//分级运算函数int fkh (char sz[N], char ccu[N], int icu[N], int h0);//主运算函数int main(){  int i1,i2,d=1,icu[N],kh=0,jg,j=0,h0;//icu[N]用于存放变量值,kh括号计数,jg存放结果  int bj=0,hq[N],h=0,x=0,xq[N];//hq[N]存放合取结果xq[N]存放析取结果  char sz[N],ccu[N],sz0[N],s;//sz[N]存放式子,ccu[N]存放变量,sz0[N]也是用于存放式子  hq[0]=-1;  xq[0]=-1;  gets(sz);//读取式子  strcpy(sz0,sz);//复制式子  int l=strlen(sz);  if(l==1){  if(sz[0]>='a'&&sz[0]<='z') printf("m1 ; M0\n");  else printf("0 ; M0\n");  return 0;  }  for(i1=0;i1<strlen(sz);i1++)  {    if(sz[i1]==')' || sz[i1]=='(')//存储括号数量      kh++;    if(sz[i1]>='a' && sz[i1]<='z' || sz[i1]>='A' && sz[i1]<='Z')     {      for(i2=0;i2<j;i2++) //判断并储存变量。      if(ccu[i2]==sz[i1])//去除重复变量        d=0;      if(d==1)  {        ccu[j]=sz[i1];        j++;      }      d=1;     }  }  h0=j;     for(i1=0;i1<j;i1++) ///////先将所有的变量赋值为零。    icu[i1]=0;  jg=tkh(sz,ccu,icu,h0); //用函数求结果  if(jg==0)//结果为0,合取加1    hq[h++]=bj;  else //否则,析取加1    xq[x++]=bj;       strcpy(sz,sz0);   for(i1=0;i1<(int)pow(2,j)-1;i1++)  {    ++bj;    panduan(icu,j-1); //赋值变量    jg=tkh(sz,ccu,icu,h0);     if(jg==0)//结果为0,合取加1      hq[h++]=bj;    else //否则,析取加1      xq[x++]=bj;     strcpy(sz,sz0); //恢复被修改的数组。  }   if(xq[0]==-1)//不存在析取范式时    printf("0 ; ");  else  {    for(i1=0;i1<x;i1++)  {        if (i1>0)//判断并添加符号           printf(" ∨ ");           printf("m%d",xq[i1]);//输出主析取范式  }   printf(" ; ");  }   if(hq[0]==-1)//不存在合取范式时    printf("1");  else  {     for(i1=0;i1<h;i1++){  if (i1>0)//判断并添加符号        printf(" ∧ ");      printf("M%d",hq[i1]); //输出主合取范式}  }  printf("\n"); } void panduan(int b[N],int f) // 二进制赋值。 {  int i;  i=f;  if(b[f]==0)//加1    b[f]=1;  else//进位  {    b[f]=0;    panduan(b,--i);  } } int tkh (char sz[N],char ccu[N],int icu[N],int h0)//分级运算函数{  int i,j,h,s,kh=0,wz[N],a;   char xs1[N],ckh[N]; //xs1用来保存括号内的字符 ckh用来保存括号。  s=strlen(sz);  for(i=0;i<s;i++)  if(sz[i]=='(' || sz[i]==')')//判断括号  {    wz[kh]=i;//存储括号位置    ckh[kh]=sz[i];//存储括号类型    kh++;  }  if(kh==0)    return fkh(sz,ccu,icu,h0);//如果无括号,直接运行  else  {    for(i=0;i<kh;i++)    if(ckh[i]==')')//找到第一个)      break;    for(j=wz[i-1]+1,h=0;j<wz[i];j++,h++) //存储最内级括号中的内容      xs1[h]=sz[j];     xs1[h]='\0';    a=fkh(xs1,ccu,icu,h0);//运行最内级括号的式子,得到结果    if(a==1)//判断并存储结果      sz[wz[i-1]]=1;    else      sz[wz[i-1]]=-2;    for(j=wz[i-1]+1;j<s+wz[i-1]-wz[i];j++)//将括号后内容前移      sz[j]=sz[j+wz[i]-wz[i-1]];    sz[j]='\0';     return tkh(sz,ccu,icu,h0);//循环执行  }} int fkh(char sz[N],char ccu[N],int icu[N],int h0)//主运算函数{  int i,h=0,j=0,j1=0,j2=0,j3=0,j4=0,j5=0,i1,i2,p1=-1,p2=-1,s;  char dt[N];  s=strlen(sz);  if(s==1)  if(sz[0]==-2)//判断是否是最后一项    return 0;  else    return 1; //1 就是sz[0]的值、  else  {     for(i=0;i<s-j;i++) //先处理非    if(sz[i]=='!'){       for(i1=0;i1<h0;i1++)      if(sz[i+1]==ccu[i1])//将变量赋值并给P1        p1=icu[i1];      if(sz[i+1]==-2)//如果是前运算结果的0,则P1等于0        p1=0;       if(p1==-1)//如果是数字,直接给P1        p1=sz[i+1];       dt[j+2]=!p1;//非运算      sz[i]=j+2;      j++;      p1=0;      for(i1=i+1;i1<s-j;i1++)        sz[i1]=sz[i1+1];//将后续式子前移一项}    p1=-1;     j1=j;     for(i=0;i<s-j1-2*j2;i++) // 处理与    if(sz[i]=='&'){       for(i1=0;i1<h0;i1++)  {         if(sz[i-1]==ccu[i1])//将变量赋值并给P1          p1=icu[i1];        if(sz[i+1]==ccu[i1])//将变量赋值并给P2          p2=icu[i1];  }      for(i2=2;i2<j+2;i2++)   {        if(sz[i-1]==i2) //如果为前计算结果,将结果赋值并给P1          p1=dt[i2];         if(sz[i+1]==i2) //如果为前计算结果,将结果赋值并给P2          p2=dt[i2];  }      if(sz[i-1]==-2)//如果是前运算结果的0,则P1等于0        p1=0;       if(sz[i+1]==-2)//如果是前运算结果的0,则P2等于0        p2=0;      if(p1==-1) //如果是数字,直接给P1        p1=(int)(sz[i-1]);      if(p2==-1)//如果是数字,直接给P2        p2=(int)(sz[i+1]);       dt[j+2]=p1 && p2;//与运算      sz[i-1]=j+2;      j++;      j2++;      p1=-1;      p2=-1;       for(i1=i;i1<s-j1-2*j2;i1++)//将后续式子前移两项        sz[i1]=sz[i1+2];      i=i-1;}    for(i=0;i<s-j1-2*j2-2*j3;i++) // 处理或。       if(sz[i]=='|')  {        for(i1=0;i1<h0;i1++){           if(sz[i-1]==ccu[i1])//将变量赋值并给P1            p1=icu[i1];          if(sz[i+1]==ccu[i1])//将变量赋值并给P2            p2=icu[i1];}        for(i2=2;i2<j+2;i2++) {          if(sz[i-1]==i2)  //如果为前计算结果,将结果赋值并给P1            p1=dt[i2];          if(sz[i+1]==i2)//如果为前计算结果,将结果赋值并给P2            p2=dt[i2];}        if(sz[i-1]==-2)//如果是前运算结果的0,则P1等于0          p1=0;         if(sz[i+1]==-2)//如果是前运算结果的0,则P2等于0          p2=0;        if(p1==-1)//如果是数字,直接给P1          p1=sz[i-1];        if(p2==-1)//如果是数字,直接给P2          p2=sz[i+1];        dt[j+2]=p1 || p2;//或运算        sz[i-1]=j+2;        j++;        j3++;        p1=-1;        p2=-1;         for(i1=i;i1<s-j1-2*j2-2*j3;i1++)//将后续式子前移两项          sz[i1]=sz[i1+2];        i--;   }      for(i=0;i<s-j1-2*j2-2*j3-2*j4;i++) // 处理蕴含。       if(sz[i]=='-')  {        for(i1=0;i1<h0;i1++){           if(sz[i-1]==ccu[i1])//将变量赋值并给P1            p1=icu[i1];          if(sz[i+1]==ccu[i1])//将变量赋值并给P2            p2=icu[i1];}        for(i2=2;i2<j+2;i2++) {          if(sz[i-1]==i2) //如果为前计算结果,将结果赋值并给P1            p1=dt[i2];          if(sz[i+1]==i2) //如果为前计算结果,将结果赋值并给P2            p2=dt[i2];}if(sz[i-1]==-2)//如果是前运算结果的0,则P1等于0      p1=0; if(sz[i+1]==-2)//如果是前运算结果的0,则P2等于0  p2=0;if(p1==-1)//如果是数字,直接给P1     p1=sz[i-1];if(p2==-1)//如果是数字,直接给P2  p2=sz[i+1];dt[j+2]=!p1 || p2;//蕴含运算sz[i-1]=j+2;j++;j4++;p1=-1;p2=-1; for(i1=i;i1<s-j1-2*j2-2*j3-2*j4;i1++)//将后续式子前移两项  sz[i1]=sz[i1+2];i--;   }  for(i=0;i<s-j1-2*j2-2*j3-2*j4-2*j5;i++) // 处理等值。   if(sz[i]=='+')  {    for(i1=0;i1<h0;i1++){           if(sz[i-1]==ccu[i1])//将变量赋值并给P1            p1=icu[i1];          if(sz[i+1]==ccu[i1])//将变量赋值并给P2            p2=icu[i1];}        for(i2=2;i2<j+2;i2++) {          if(sz[i-1]==i2) //如果为前计算结果,将结果赋值并给P1            p1=dt[i2];          if(sz[i+1]==i2) //如果为前计算结果,将结果赋值并给P2            p2=dt[i2];}        if(sz[i-1]==-2)//如果是前运算结果的0,则P1等于0          p1=0;         if(sz[i+1]==-2)//如果是前运算结果的0,则P2等于0          p2=0;        if(p1==-1)//如果是数字,直接给P1          p1=sz[i-1];        if(p2==-1)//如果是数字,直接给P2          p2=sz[i+1];        dt[j+2]=(!p1 || p2)&&(!p2 || p1);//等值运算        sz[i-1]=j+2;        j++;        j5++;        p1=-1;        p2=-1;         for(i1=i;i1<s-j1-2*j2-2*j3-2*j4-2*j5;i1++)//将后续式子前移两项          sz[i1]=sz[i1+2];        i--;   }      return dt[j+1];//返回结果    }}


1 0
原创粉丝点击