实现功能:输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式。
输入:命题公式的合式公式
输出:公式的主析取范式和主析取范式,输出形式为:“ mi ∨ mj ; Mi ∧ Mj” ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用“ ; ”隔开,“ ; ”前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范式为 0 。
输入公式的符号说明:
! 非,相当于书面符号中的 “ ¬ ”
& 与,相当于书面符号中的 “ ∧ ”
| 或,相当于书面符号中的 “ ∨ ”
- 蕴含联结词,相当于书面符号中的 “ → ”
+ 等价联结词,相当于书面符号中的 “ ↔ ”
( 前括号
) 后括号
#include<bits/stdc++.h>
using namespace std;
char expression[100];
int alphbet[26]={0};
int pos[30] = {0};
int k = 0;
int get_priority(char a){
int re = 0;
switch (a){
case '(':re = 1;break;
case '!':re = 8;break;
case '|':re = 6;break;
case '&':re = 7;break;
case '-':re = 4;break;
case '+':re = 3;break;
}
return re;
}
void addsome(){
alphbet[pos[0]]++;
for(int i = 0;i < k-1;i++){
if(alphbet[pos[i]] > 1){
alphbet[pos[i+1]] += 1;
alphbet[pos[i]] = 0;
}
}
//for(int i =0 ;i< k;i++) cout << alphbet[pos[i]] << " ";
//cout << endl;
}
bool calc(int num){
stack < bool > value;bool tmp1,tmp2;
// for(int j = 0;j < k-1;j++){
// cout << alphbet[pos[j]] << ",";
// }
// cout << endl;
for(int j = 0;j < num;j++){
//利用栈计算真值
switch(expression[j]){
case 'z': value.push(alphbet[expression[j] - 'a']);break;
case '!': tmp1 = value.top();value.pop();value.push(!tmp1);break;
case '|': tmp1 = value.top();value.pop();tmp2 = value.top();value.pop();
value.push(tmp1 || tmp2);break;
case '&':tmp1 = value.top();value.pop();tmp2 = value.top();value.pop();
value.push(tmp1 && tmp2);break;
case '-':tmp2 = value.top();value.pop();tmp1 = value.top();value.pop();
if(tmp1 == true && tmp2 == false){
value.push(false);
}else{
value.push(true);
}break;
case '+': tmp1 = value.top();value.pop();tmp2 = value.top();value.pop();
value.push(tmp1 == tmp2);break;
default : break;
}
}
return value.top();
}
int main(){
stack <char> ops;
// 用于记录字母位置,同时便于枚举所有“赋值”进行真值计算的数组
//用于记录成真赋值
int real[30] = {0};
//记录成假赋值
int notruth[30] = {0};
int i = 0,realint = 0,notint = 0;
char c;
// 中缀转后缀,后缀表达式保存在一个数组中
while((c = getchar()) != '\n'){
//if(c == ' ') continue;
//cout << c << endl;
if((c >= 'a') && (c <= 'z')){
//---------------------------------------c是操作数
expression[i++] = c;//字母放到后缀数组中
alphbet[c-'a']++;//方便后续统计出现多少种字母,对每种字母进行赋值
}else{
// -------------------------------------------c为操作符
if(ops.empty() || c == '('){
ops.push(c);
}else{
if(c == ')'){
while(ops.top() != '('){
expression[i++] = ops.top();
ops.pop();
}
ops.pop();
}else if(get_priority(c) > get_priority(ops.top())){
ops.push(c);
}else{
while(!ops.empty() && get_priority(c) < get_priority(ops.top())){
expression[i++] = ops.top();ops.pop();
}
ops.push(c);
}
}
}
}
//输入结束弹空栈
while(!ops.empty()){
expression[i++] = ops.top();
ops.pop();
}
//cout << "end" << endl;
//for(i-1;i+1;i--) cout << expression[i] << " " ;
// 枚举,计算,保留结果
for(int j = 25;j + 1;j--){
if(alphbet[j]) pos[k++] = j;
}
//cout << k << endl;
int scal = 1;
memset(alphbet,0,sizeof(alphbet));
for(int j = 1;j <= k;j++) scal *= 2;
scal -= 1;
//cout << k << endl;
if(calc(i)) real[realint++] = 0;
else notruth[notint++] = 0;
for( int j = 1;j <= scal;j++){
//枚举
addsome();
if(calc(i)) real[realint++] = j;
else notruth[notint++] = j;
}
// 输出
if(realint == 0){
// 永假式
cout << "0 ; ";
}else{
for(int j = 0;j < realint-1;j++){
cout << "m" << real[j] << " ∨";
cout << " ";
}
cout << "m" << real[realint - 1] << " ; ";
}
if(!notint){
//永真式
cout << "1" << endl;
}else{
for(int j = 0;j < notint-1;j++){
cout << "M" << notruth[j] << " ∧ ";
}
cout << "M" << notruth[notint-1] << endl;
}
return 0;
}
该博客介绍了一个功能,输入命题公式的合式公式,可求出其真值表,并输出主合取范式和主析取范式。还说明了输入公式的符号含义,如! 表示非,& 表示与等,同时规定了输出形式。
8476

被折叠的 条评论
为什么被折叠?



