我最愛的馮老師在離散課上出了一個附加題,
為了能夠加更多的學分也是出于自己的好奇,我決定嘗試一下,
思路:二進制列舉+逆波蘭運算式
#include<stdio.h>
#include<string.h>
#define T 1
#define F 0
struct Stack{
int top;
char arr[80];
}number={-1},symbol={-1};
//number儲存后綴運算式結果
//symbol用來保存
int book[26];
int num=0;
int alphabet_true_false[26];
int enum_result[80];
char str_copy[80];
void scan_string(char str[]){
//輸入小寫字符
//例如!(p|q)>(q&!r|(r>p))
int i;
gets(str);
strcpy(str_copy,str);
int 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;
}
}
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[]){
int i,len=strlen(s);
for(i=0;i<len;i++){
if(s[i]>='a'&&s[i]<='z'){
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){
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++];
}
}
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,conjunction_top=-1,disjunction_top=-1;
int result_conjunction[80]={0},result_disjunction[80]={0};
//我要配的上她
for(i=0;i<26;i++)
if(book[i])printf("%4c|",i+'a');
putchar(' '),puts(str_copy);
for(i=0;i<(1<<num);i++){
memset(enum_result,0,num);
for(j=0;j<num;j++){
if(i&(1<<(num-j-1))){
enum_result[j]=T;
}else{
enum_result[j]=F;
}
printf("%4d|",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);
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/282152.html
標籤:其他
上一篇:2021第十二屆藍橋杯C++ B組第一場省賽賽后總結
下一篇:基于Redis實作特殊的訊息佇列
