离散数学—求主范式
来源:互联网 发布:淘宝买到假货已经下架 编辑:程序博客网 时间: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
- 离散数学—求主范式
- 离散数学 求命题公式的主范式
- 南邮离散数学实验1 (简单版) 根据真值求真值表和主范式
- 南邮离散数学实验1 (栈版) 根据表达式求真值表和主范式
- c++ 求主范式
- 离散数学之主析取范式,主合取范式
- 栈的应用——程序求主范式
- 「离散数学」 打印任意命题公示的真值表和主范式
- 离散数学输入表达式打印真值表和主析/合取范式
- 离散数学实践:真值表与范式
- C++实现离散数学求主合取范式和主析取范式
- 求命题公式的主范式
- C++实现离散数学中求合式表达式
- 离散数学 通过运算表求生成元
- 离散数学——树
- 离散数学
- 离散数学
- 离散数学
- 数据挖掘概念与技术(原书第三版)范明 孟小峰译-----第一章课后习题答案
- 数据结构—链表-单链表应用-拆分链表
- Ubuntu下使用python读取doc和docx文档的内容
- 输入学生的姓名学号成绩,并按平均分由低到高排序
- 蓝以中老师《高等代数》第07章:线性变换的Jordan标准形 笔记
- 离散数学—求主范式
- POJ.3172 Scales (DFS)
- android studio 新建assets 文件夹
- 索引的使用
- 安卓开发 切换简繁体
- Java常用类之【八种基本数据类型】
- IDEA2016.2.4 安装Python
- Codeforces gym 101149 K 想法
- poj 3624 Charm Bracelet