离散数学—求主范式

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

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

输入公式的符号说明:

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

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

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

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

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

( 前括号

) 后括号

方法一:

#include   
#include   
#include   
#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
#include
#include
#define N 1000
using 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='a' && sz[i1]<='z' || sz[i1]>='A' && sz[i1]<='Z') 
    {
      for(i2=0;i20)//判断并添加符号

           printf(" ∨ ");

           printf("m%d",xq[i1]);//输出主析取范式

  }
   printf(" ; ");
  }
   if(hq[0]==-1)//不存在合取范式时

    printf("1");

  else

  { 


    for(i1=0;i10)//判断并添加符号

        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


你可能感兴趣的:(离散数学)