北理工离散数学上机实验:消解算法

实现功能:消解算法

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

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

输入公式的符号说明:

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

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

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

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

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

( 前括号

) 后括号

整体思路:

笔者在这道题上偷懒了,直接拿第一个题求主范式的代码直接改了改,就过了。

具体思路欢迎看笔者之前的代码,当然也比较简单,各位也可以直接看代码。

全部代码:

#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
int op_rank(char a){
    switch (a)
    {
    case '(':return 0;
    case '+':return 1;
    case '-':return 2;
    case '&':return 3;
    case '|':return 4;
    case '!':return 5;
    case ')':return 6;
    }
}
bool is_in(char a,string x){
    for(unsigned int i=0;i<x.size();i++){
        if (x[i]==a) return true;
    }
    return false;
}
string post_rpn(string &input){
    string stack,output;
    int b=0;
    for(unsigned int i=0;i<input.size();i++){
        if(is_in(input[i],"()+-&|!")){
            if(input[i]==')'){
                while(stack[stack.size()-1]!='('){
                    output+=stack[stack.size()-1];
                    stack.erase(stack.begin()+stack.size()-1);
                }
                stack.erase(stack.begin()+stack.size()-1);
            }
            else{
                while((stack.size()!=0)&&op_rank((stack[stack.size()-1]))>=op_rank(input[i])&&input[i]!='('){
                    output+=stack[stack.size()-1];
                    stack.erase(stack.begin()+stack.size()-1);
                }
                stack+=input[i];
            }
        }
        else output+=input[i];
    }
    while(stack.size()!=0) {
        output+=stack[stack.size()-1];
        stack.erase(stack.begin()+stack.size()-1);
    }
    return output;
}
string how_mang_elements(string a){
    string b="";
    for(unsigned int i=0;i<a.size();i++){
        if(a[i]>='a'&&a[i]<='z'&&!is_in(a[i],b)){
            b+=a[i];
        }
    }
    for(unsigned int x=0;x<b.size();x++){
        for(unsigned int y=0;y<b.size()-x-1;y++){
            if(a[y]>a[y+1]){
                char c=a[y];
                a[y]=a[y+1];
                a[y+1]=c;
            }
        }
    }
    return b;
}
int cal(int a,int b,char c){
    if(c=='+'){
        if(a==b) return 1;
        else return 0;
    }
    else if(c=='-'){
        if(a==1&&b==0) return 0;
        else return 1;
    }
    else if(c=='|'){
        if(a+b>=1) return 1;
        else return 0;
    }
    else if(c=='&') {return a*b;}
    else if(c=='!') {
        if(a==1) return 0;
        else return 1;
    }
}
int calculate(string a){
    while(a.size()>1){
        for(unsigned int i=0;i<a.size();i++){
        if(is_in(a[i],"+|&-!")){
            if(a[i]!='!'){
                a[i-2]=char(cal(int(a[i-2]-'0'),int(a[i-1]-'0'),a[i])+'0');
                a.erase(a.begin()+i-1);
                a.erase(a.begin()+i-1);
                break;
            } 
            else{
                a[i-1]=char(cal(int(a[i-1]-'0'),0,a[i])+'0');
                a.erase(a.begin()+i);
                break;
            }
        }
        }
    }
    return int(a[0]-'0');
}
int where_is_element(string number0,char a){
    for(int i=0;i<number0.size();i++){
        if(number0[i]==a) return i;
    }
}
bool bianli(string number,string output2){
    string a="",number0=number;
    int c[500],d=0;
    for(int i=0;i<pow(2,number.size());i++){
        int p=i;
        a="";
        while(p!=0){
            a=char(p%2+'0')+a;
            p=p>>1;
        }
        int b=0;
        for(unsigned int j=0;j<number.size();j++){
            if(a.size()<number.size()-j) number[j]='0';
            else number[j]=a[b++];
        }
        string output=output2;
        for(unsigned int i=0;i<output.size();i++){
            if(output[i]>='a'&&output[i]<='z') {
                output[i]=number[where_is_element(number0,output[i])];
            }
        }
        if(calculate(output)==1) {return true;}
    }
        return false;
}
int main(void){
    string input;
    cin>>input;
    if(bianli(how_mang_elements(post_rpn(input)),post_rpn(input))) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}

代码较为简单,大家自行分析就好,笔者不多赘述了。

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值