我最爱的冯老师在离散课上出了一个附加题。
为了能够加更多的学分也是出于自己的好奇,我决定尝试一下。
思路:二进制枚举+逆波兰表达式

#include<stdio.h>
#include<string.h>
#define T 1
#define F 0struct Stack{int top;char arr[80];
}number={-1},symbol={-1};
//number储存后缀表达式结果
//symbol 操作符栈,用来保存操作符 int book[26];//记录变元元素和个数
//a对应下标为0
//b对应下标为1
//c对应下标为2
//以此类推
int num=0;//记录变元的个数
int alphabet_true_false[26];
/*
上面的book数组每个元素存放的是
该下标对应的字母是否存在类似的这个alphabet_true_false存放的是
该下标对应的字母变元的真值(true or false)
当然,只有book[i]不为零的情况下该数组才会奏效
*/
int enum_result[80];
/*
如果二进制值为110110010
那么该数组从前往后数每个元素分别为:
1 1 0 1 1 0 0 1 0
说白了就是把十进制转为二进制01值并存到enum_result里罢了
*/char str_copy[80];//输入的字符串的副本 void count_num(char str[]){//记录变元的个数,用全局变量num储存 int i,len=strlen(str);for(i=0;i<len;i++){if(str[i]>='a'&&str[i]<='z'){if(book[str[i]-'a']==0){ book[str[i]-'a']=1;    ++num; } }      }
}void scan_string(char str[]){//输入小写字符//例如!(p|q)>(q&!r|(r>p)) int i;gets(str);strcpy(str_copy,str);count_num(str);//记录变元的个数,用全局变量num储存 int len=strlen(str);for(i=0;i<len;i++){//对操作符进行优先级处理//把字符数组的操作符改为计算机可判断优先级的特别字符 switch(str[i]){case '!':str[i]=')'+5;break;case '&':str[i]=')'+4;break;case '|':str[i]=')'+3;break;case '>':str[i]=')'+2;break;case '=':str[i]=')'+1;break;}        }
}void reverse_polish(char s[]){//把命题公式改为后缀表达式//并把后缀处理的结果保存在number结构体里//number结构体里原本存放的是变元,就是那些字母。//symbol里存放的是操作符, 经过后缀处理完后symbol里应该为空。 //经过后缀处理完后就会把symbol里的操作符也转移到了number里 int i,len=strlen(s);for(i=0;i<len;i++){if(s[i]>='a'&&s[i]<='z'){//如果是命题变元就直接入number栈 number.arr[++number.top]=s[i];          }else if(s[i]>')'&&s[i]<=5+')'){if(symbol.top==-1||symbol.arr[symbol.top]==')'){++symbol.top;symbol.arr[symbol.top]=s[i];}else if(s[i]>=symbol.arr[symbol.top]){++symbol.top;symbol.arr[symbol.top]=s[i];}else{while(symbol.top!=-1&&s[i]<symbol.arr[symbol.top]){++number.top;number.arr[number.top]=symbol.arr[symbol.top];--symbol.top;}--i;}}else if(s[i]=='('||s[i]==')'){if(s[i]=='('){++symbol.top;symbol.arr[symbol.top]=s[i];}else{while(symbol.arr[symbol.top]!='('){++number.top;number.arr[number.top]=symbol.arr[symbol.top];--symbol.top;              }if(symbol.top!=-1)--symbol.top;}}       }while(symbol.top!=-1){++number.top;number.arr[number.top]=symbol.arr[symbol.top];--symbol.top;                                }
}int check(int num){//判断enum_result[]的二进制情况组成的是极小值(return 1)还是极大值(return 0)struct Stack ans={-1};int i,k=0,len=0,temp;for(i=0;i<26;i++){if(book[i]){++len;alphabet_true_false[i]=enum_result[k++];//enum_result里只有真或假(1,0) //这一步类似于变元p被赋值为false(0)//或者t被赋值为true(1)}}for(i=0;i<=number.top;i++){if(number.arr[i]>='a'&&number.arr[i]<='z'){++ans.top;ans.arr[ans.top]=alphabet_true_false[number.arr[i]-'a'];}else{switch(number.arr[i]){case '.':ans.arr[ans.top]=!ans.arr[ans.top];break;case '-':ans.arr[ans.top-1]=ans.arr[ans.top-1]&ans.arr[ans.top];--ans.top;break;case ',':ans.arr[ans.top-1]=ans.arr[ans.top-1]|ans.arr[ans.top];--ans.top;break;case '+':ans.arr[ans.top-1]=!ans.arr[ans.top-1]|ans.arr[ans.top];--ans.top;break;case '*':ans.arr[ans.top-1]=(!ans.arr[ans.top-1]|ans.arr[ans.top])&(!ans.arr[ans.top]|ans.arr[ans.top-1]);--ans.top;break;}}}printf("%4d\n",ans.arr[0]); return ans.arr[0];
}void binary_enumeration(int num){//二进制枚举 2^num次 遍历所有情况 //int i,j;int conjunction_top=-1,disjunction_top=-1;/*也把下面的两个数组看作栈,使用这两个top变量指向的就是栈顶元素的下标 */ int result_conjunction[80]={0};//储存的是主合取结果 int result_disjunction[80]={0};//储存的是主析取结果 for(i=0;i<26;i++)if(book[i])printf("%4c|",i+'a');putchar(' '),puts(str_copy);//二进制枚举用的是两层循环//最外面的一层循环如果num是4//则1<<num的二进制就为(1111),十进制就是15//说白了就是循环15次,让变量i自增15次 //而里面的循环则是://读取变量i的二进制中的第j位比特值//假如变量i位5,则i的二进制就是101// for(i=0;i<(1<<num);i++){// memset(enum_result,0,num);for(j=0;j<num;j++){//这一层的循环说白了就是把变量j的值转换为对应的二进制,并把二进制值储存到enum_result数组里 if(i&(1<<(num-j-1))){enum_result[j]=T;}else{enum_result[j]=F;}printf("%4d|",enum_result[j]);}//里层循环完之后现在的enum_result每一位里存放的就是j的二进制对应的值 if(check(num)){result_disjunction[++disjunction_top]=i;//主析取十进制下标 }else{result_conjunction[++conjunction_top]=i;//主合取十进制下标 }}puts("\n主析取范式为:");for(i=0;i<=disjunction_top;i++){printf("m%d%s",result_disjunction[i],i^disjunction_top?"&":"");}puts("\n主合取范式为:");for(i=0;i<=conjunction_top;i++){printf("M%d%s",result_conjunction[i],i^conjunction_top?"|":"");}
}void show(char str[]){int i; puts("\n后缀表达式为:");for(i=0;i<=number.top;i++){switch(number.arr[i]){case ')'+5:number.arr[i]='!';break;case ')'+4:number.arr[i]='&';break;case ')'+3:number.arr[i]='|';break;case ')'+2:number.arr[i]='>';break;case ')'+1:number.arr[i]='=';break;} printf("%c",number.arr[i]);}puts("\n使用的命题变项:");for(i=0;i<26;i++)if(book[i])printf("%c ",i+'a');
}/*优先级
非  :!      5
合取:&       4
析取:|       3
蕴涵:>       2
等价:=       1
*/int main()
{int i=0;char str[80];scan_string(str);//输入小写字符reverse_polish(str);//逆波兰表达式 去括号 binary_enumeration(num);//把变元个数num传入函数//有num个变元就有2^num个情况,对每一个二进制情况经进行heck(), show(str);return 0;
}

大一,寒假时为了蓝桥杯学了不少算法和数据结构的知识。
写了将近4个小时。又复习了一遍后缀表达式。
算法方面没有什么不理解的地方,大部分时间都是细节上的错误,
比如

for(i=0;i<=number.top;i++){switch(number.arr[i]){...}
}

写成

for(i=0;i<=number.top;i++){switch(number.arr[number.top]){//循环的是i,我却循环成了栈顶元素。这个地方卡了差不多一个小时。可能是因为太晚了脑子有点糊涂...}
}

程序跑通了调的没bug了之后拿给老师看,老师理所当然的给出了肯定的评价;
就是不知道她什么时候能把我这个分给加上。

以下是运行结果:

为了配的上我心中的那个执念
lonely but only study
lonely but only suppress

用C语言求解合式公式的主合取范式和主析取范式相关推荐

  1. 命题公式的主合取范式C语言,用C或C++编写程序,要求:输入命题公式,给出它的主合取范式和主析取范式....

    共回答了18个问题采纳率:83.3% A-Z + is OR * is AND _ is → # is♁(圆圈里加个+) @ is ⊙ $ is ↑ 命题的"与非" 运算( &qu ...

  2. 命题公式的主合取范式C语言,命题公式主范式的自动生成与形式输出.pdf

    收稿日期 2006 04 19 作者简介 张会凌 1954 男 甘肃成县人 甘肃联合大学数学与信息学院副教授 主要从事微分几何与计算机方面 的研究 文章编号 1672 691X 2006 05 004 ...

  3. 离散数学 求命题公式的主析取范式和主合取范式

    Description 输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式. Input 命题公式的合式公式 Output 公式的主析取范式和主合取范式,输出形式为:&qu ...

  4. 使用C++求命题公式的主析取范式与主合取范式

    最近的离散数学的一个上机作业,要求任意输入一个命题公式,求它的真值表与主析取范式和主合取范式.其中的命题连接词都是用特殊符号来表示(怕麻烦--),并最终选择使用C++来编写程序. 先贴代码: // 五 ...

  5. 离散数学范式c语言实验报告,离散数学实验报告-利用真值表法求主析取范式及主合取范式的实现...

    1.实 验 报 告( / 学年 第 一 学期)课程名称离散数学实验名称利用真值表法求主析取范式及主合取范式的实现实验时间年月日指导单位指导教师学生姓名班级学号学院(系)专 业 实 验 报 告实验名称利 ...

  6. 命题公式的主合取范式C语言,程序设计题: 命题逻辑应用系统

    命题逻辑应用系统 1 问题描述 该系统要求实现命题逻辑中基本算法及其应用系统,包括真值表的计算.主析取和主合取范式的计算.通过此课题,熟练掌握命题公式的计算机表示.命题等价常见算法的实现,实现一个简单 ...

  7. 【离散数学】Java语言实现利用真值表法求主析取范式和主合取范式

    C++版本的看这个链接: [离散数学]C++语言实现利用真值表法求主析取范式和主合取范式_zhtstar的博客-CSDN博客https://blog.csdn.net/weixin_56319483/ ...

  8. 【离散数学】C++语言实现利用真值表法求主析取范式和主合取范式

    Java版本的如下链接所示: Java语言实现利用真值表法求主析取范式和主合取范式_zhtstar的博客-CSDN博客https://blog.csdn.net/weixin_56319483/art ...

  9. c语言编程输出主析取范式,c++编程:从键盘上任意输入一个主析取范式,输出与之等值的主合取范式...

    满意答案 zxuu11 2013.09.15 采纳率:44%    等级:8 已帮助:2365人 //从键盘上任意输入一个主析取范式,输出与之等值的主合取范式.┐∧∨ # include # incl ...

  10. 用c语言求解n阶线性矩阵方程组,用C语言求解N阶线性矩阵方程Axb简单解法.docx

    用C语言求解N阶线性矩阵方程Axb简单解法 用C语言求解N阶线性矩阵方程Ax=b的简单解法一.描述问题:题目:求解线性方程组Ax=b,写成函数.其中,A为n×n的N阶矩阵,x为需要求解的n元未知数组成 ...

最新文章

  1. 知乎推荐页Ranking构建历程和经验分享
  2. Python-OpenCV 处理视频(五): 运动方向判断
  3. Redis 从入门到起飞(上)
  4. VR全景看年评!PConline年度评测盛典等你来体验
  5. 消息队列---消息模型及使用场景
  6. 【原创】OllyDBG 入门系列(七)-汇编功能
  7. Django中的request和response
  8. WORDNET与HOWNET之比较
  9. axure element ui素材_Element - 饿了么团队出品的神级桌面 UI 组件库
  10. 华为终端穿戴软件测试,【华为软件测试工程师面试】总共五轮面试外加一个上机的性格测试。-看准网...
  11. 主页被强制绑定为360导航
  12. 入门DP教程(超详细)
  13. linux麒麟镜像,银河麒麟、优麒麟的软件源和镜像站
  14. Unity3D中2D图片动画进行帧动画播放
  15. Mac电脑中delete键的几种用法
  16. Excel Rate 函数的JavaScript 实现,等额本息计算反推利率
  17. linux环境下常用的查找命令find、which、grep
  18. 软件工程(第三版) 期末复习
  19. yocto 下载代理
  20. 漫画|电话会议炸出了同事里的隐形富豪

热门文章

  1. dep指定版本 go_Golang官方依赖管理工具:dep
  2. 计算机没有光驱降无法启动,windows 未能启动 原因可能是最近更改了硬件或软件 没有光驱怎么办...
  3. c语言给字母加密,C语言文字简单加密程序的实现
  4. 2021-03-08动力学方程
  5. java字符串不足长度自动补0
  6. 计算机无法添加本地策略组,电脑打不开本地组策略编辑器,求破~!
  7. iOS 越狱检测/反越狱
  8. android蜂巢效果、环形菜单、Kotlin影视应用、简约时钟、查看导出App、支付宝AR扫码效果等源码
  9. 执行以下代码后,可以看到小猫在舞台上右转了4次正好一圈。
  10. 公众号添加百度网盘链接