C語言(遞迴法構造答案全集)2018刑偵科推理試題
阿新 • • 發佈:2019-02-14
今年早些時候,這張圖片火遍了網路,當時就想著,這個題目用計算機來解,應該是很方便的。無奈當時工作忙,沒有時間弄。最近時間閒,就鼓搗了一下,花費幾個小時,成功執行得出答案。但上網一看,各路大神早就給出了N種解法。其中找到一篇和我一樣用暴力窮舉實現的。我的解法和他的相比,區別在:我窮舉所有答案時,是用遞迴演算法實現的。再和另一篇C語言解法作者比較,他是用進位的思想遍歷所有答案,節省的是儲存空間。而我是一開始就把答案列出來,用空間換時間;在我自己的電腦上執行,速度比他的程式快3倍左右。
思路:
1.構建一個答案集,囊括所有答案,有4^10種,共1048576個,編號從0編到1048575。
2.將每個題目看作一個命題,把命題的選項作為引數,定義10個判斷函式,如果選項正確,函式就返回真值。
3.從編號0開始判斷到1048576,發現一個正確答案就將編號壓棧,最後將所有正確答案打印出來。
廢話少說上程式碼:
#include<stdio.h> #define BOOL char #define TRUE 1 #define FALSE 0 struct answer{ //定義答案結構,answer下標從0-9代表1-10題的答案 char index[10]; }; void init_answer_set(struct answer* answer_set,int low,int high,int indexNum){//初始化答案陣列函式,遞迴演算法構造所有答案的陣列。low和high代表答案編號範圍。 int area = (high-low +1)/4; int i; if (indexNum==9){ for(i=0;i<4;i++){ answer_set[low+i].index[indexNum]='a'+i; } }else{ for(i=0;i<area;i++){ answer_set[low+i].index[indexNum]='a'; answer_set[low+area+i].index[indexNum]='b'; answer_set[low+area*2+i].index[indexNum]='c'; answer_set[low+area*3+i].index[indexNum]='d'; } init_answer_set(answer_set,low,low+area-1,indexNum+1); init_answer_set(answer_set,low+area,low+area*2-1,indexNum+1); init_answer_set(answer_set,low+area*2,low+area*3-1,indexNum+1); init_answer_set(answer_set,low+area*3,low+area*4-1,indexNum+1); } } int printf_answer(struct answer* answer_set,int num){ //定義列印函式,引數num,列印編號為num的答案 int i; if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } printf("這是第%d個答案\n",num); for(i=0;i<10;i++){ printf("%c\t",answer_set[num].index[i]); } printf("\n"); return 1; } BOOL question0(struct answer* answer_set,int num){//第一題的命題判斷函式 ,雖然沒什麼資訊量,本來可以不寫,但為了程式碼看起來整齊,不缺斤少兩,還是寫上吧。 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[0]<97||answer_set[num].index[0]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[0]=='a'){//答案為a時 if(answer_set[num].index[0]=='a') return 1; else return 0; } if(answer_set[num].index[0]=='b'){//答案為b時 if(answer_set[num].index[0]=='b') return 1; else return 0; } if(answer_set[num].index[0]=='c'){//答案為c時 if(answer_set[num].index[0]=='c') return 1; else return 0; } if(answer_set[num].index[0]=='d'){//答案為d時 if(answer_set[num].index[0]=='d') return 1; else return 0; } } BOOL question1(struct answer* answer_set,int num){//第二題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[1]<97||answer_set[num].index[1]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[1]=='a'){//答案為a時 if(answer_set[num].index[4]=='c') return 1; else return 0; } if(answer_set[num].index[1]=='b'){//答案為b時 if(answer_set[num].index[4]=='d') return 1; else return 0; } if(answer_set[num].index[1]=='c'){//答案為c時 if(answer_set[num].index[4]=='a') return 1; else return 0; } if(answer_set[num].index[1]=='d'){//答案為d時 if(answer_set[num].index[4]=='b') return 1; else return 0; } } BOOL question2(struct answer* answer_set,int num){//第三題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[2]<97||answer_set[num].index[2]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[2]=='a'){//答案為a時 if(answer_set[num].index[5]==answer_set[num].index[1]&&answer_set[num].index[5]==answer_set[num].index[3]&&answer_set[num].index[2]!=answer_set[num].index[5]) return 1; else return 0; } if(answer_set[num].index[2]=='b'){//答案為b時 if(answer_set[num].index[2]==answer_set[num].index[1]&&answer_set[num].index[2]==answer_set[num].index[3]&&answer_set[num].index[5]!=answer_set[num].index[2]) return 1; else return 0; } if(answer_set[num].index[2]=='c'){//答案為c時 if(answer_set[num].index[2]==answer_set[num].index[5]&&answer_set[num].index[2]==answer_set[num].index[3]&&answer_set[num].index[1]!=answer_set[num].index[2]) return 1; else return 0; } if(answer_set[num].index[2]=='d'){//答案為d時 if(answer_set[num].index[2]==answer_set[num].index[5]&&answer_set[num].index[2]==answer_set[num].index[1]&&answer_set[num].index[3]!=answer_set[num].index[2]) return 1; else return 0; } } BOOL question3(struct answer* answer_set,int num){//第四題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[3]<97||answer_set[num].index[3]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[3]=='a'){//答案為a時 if(answer_set[num].index[0]==answer_set[num].index[4]) return 1; else return 0; } if(answer_set[num].index[3]=='b'){//答案為b時 if(answer_set[num].index[1]==answer_set[num].index[6]) return 1; else return 0; } if(answer_set[num].index[3]=='c'){//答案為c時 if(answer_set[num].index[0]==answer_set[num].index[8]) return 1; else return 0; } if(answer_set[num].index[3]=='d'){//答案為d時 if(answer_set[num].index[5]==answer_set[num].index[9]) return 1; else return 0; } } BOOL question4(struct answer* answer_set,int num){//第五題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[4]<97||answer_set[num].index[4]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[4]=='a'){//答案為a時 if(answer_set[num].index[4]==answer_set[num].index[7]) return 1; else return 0; } if(answer_set[num].index[4]=='b'){//答案為b時 if(answer_set[num].index[4]==answer_set[num].index[3]) return 1; else return 0; } if(answer_set[num].index[4]=='c'){//答案為c時 if(answer_set[num].index[4]==answer_set[num].index[8]) return 1; else return 0; } if(answer_set[num].index[4]=='d'){//答案為d時 if(answer_set[num].index[4]==answer_set[num].index[6]) return 1; else return 0; } } BOOL question5(struct answer* answer_set,int num){//第六題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[5]<97||answer_set[num].index[5]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[5]=='a'){//答案為a時 if(answer_set[num].index[7]==answer_set[num].index[1]&&answer_set[num].index[7]==answer_set[num].index[3]) return 1; else return 0; } if(answer_set[num].index[5]=='b'){//答案為b時 if(answer_set[num].index[7]==answer_set[num].index[0]&&answer_set[num].index[7]==answer_set[num].index[5]) return 1; else return 0; } if(answer_set[num].index[5]=='c'){//答案為c時 if(answer_set[num].index[7]==answer_set[num].index[2]&&answer_set[num].index[7]==answer_set[num].index[9]) return 1; else return 0; } if(answer_set[num].index[5]=='d'){//答案為d時 if(answer_set[num].index[7]==answer_set[num].index[4]&&answer_set[num].index[7]==answer_set[num].index[8]) return 1; else return 0; } } BOOL isMin(struct answer* answer_set,int num,char option){//第七題判斷函式 看字元答案option是否是最少選項,如果是,就返回1,否則返回0 int count_a=0; int count_b=0; int count_c=0; int count_d=0; int indexNum; char min; for (indexNum=0;indexNum<10;indexNum++){ if (answer_set[num].index[indexNum]=='a') count_a=count_a+1; else if(answer_set[num].index[indexNum]=='b') count_b=count_b+1; else if(answer_set[num].index[indexNum]=='c') count_c=count_c+1; else if(answer_set[num].index[indexNum]=='d') count_d=count_d+1; } if (count_a<count_b&&count_a<count_c&&count_a<count_d) min='a'; else if(count_b<count_a&&count_b<count_c&&count_b<count_d) min='b'; else if(count_c<count_a&&count_c<count_b&&count_c<count_d) min='c'; else if(count_d<count_a&&count_d<count_b&&count_d<count_c) min='d'; else min=0; if(option == min) return 1; else return 0; } BOOL question6(struct answer* answer_set,int num){//第七題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[6]<97||answer_set[num].index[6]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[6]=='a'){//答案為a時 if(isMin(answer_set,num,'c')) return 1; else return 0; } if(answer_set[num].index[6]=='b'){//答案為b時 if(isMin(answer_set,num,'b')) return 1; else return 0; } if(answer_set[num].index[6]=='c'){//答案為c時 if(isMin(answer_set,num,'a')) return 1; else return 0; } if(answer_set[num].index[6]=='d'){//答案為d時 if(isMin(answer_set,num,'d')) return 1; else return 0; } } BOOL question7(struct answer* answer_set,int num){//第八題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[7]<97||answer_set[num].index[7]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[7]=='a'){//答案為a時 if((answer_set[num].index[6]-1!=answer_set[num].index[0])&&(answer_set[num].index[6]+1!=answer_set[num].index[0])) return 1; else return 0; } if(answer_set[num].index[7]=='b'){//答案為b時 if((answer_set[num].index[4]-1!=answer_set[num].index[0])&&(answer_set[num].index[4]+1!=answer_set[num].index[0])) return 1; else return 0; } if(answer_set[num].index[7]=='c'){//答案為c時 if((answer_set[num].index[1]-1!=answer_set[num].index[0])&&(answer_set[num].index[1]+1!=answer_set[num].index[0])) return 1; else return 0; } if(answer_set[num].index[7]=='d'){//答案為d時 if((answer_set[num].index[9]-1!=answer_set[num].index[0])&&(answer_set[num].index[9]+1!=answer_set[num].index[0])) return 1; else return 0; } } BOOL question8(struct answer* answer_set,int num){//第九題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[8]<97||answer_set[num].index[8]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[8]=='a'){//答案為a時 if((answer_set[num].index[0]==answer_set[num].index[5])!=(answer_set[num].index[5]==answer_set[num].index[4])) return 1; else return 0; } if(answer_set[num].index[8]=='b'){//答案為b時 if((answer_set[num].index[0]==answer_set[num].index[5])!=(answer_set[num].index[9]==answer_set[num].index[4])) return 1; else return 0; } if(answer_set[num].index[8]=='c'){//答案為c時 if((answer_set[num].index[0]==answer_set[num].index[5])!=(answer_set[num].index[1]==answer_set[num].index[4])) return 1; else return 0; } if(answer_set[num].index[8]=='d'){//答案為d時 if((answer_set[num].index[0]==answer_set[num].index[5])!=(answer_set[num].index[8]==answer_set[num].index[4])) return 1; else return 0; } } int max_Minus_min(struct answer* answer_set,int num){//第10題函式 int count[4]={0,0,0,0}; int indexNum; int temp,i,j; for (indexNum=0;indexNum<10;indexNum++){ if (answer_set[num].index[indexNum]=='a') count[0]=count[0]+1; else if(answer_set[num].index[indexNum]=='b') count[1]=count[1]+1; else if(answer_set[num].index[indexNum]=='c') count[2]=count[2]+1; else if(answer_set[num].index[indexNum]=='d') count[3]=count[3]+1; } for(i=0;i<3;i++){ for(j=0;j<3-i;j++) if(count[j]>count[j+1]){ temp=count[j]; count[j]=count[j+1]; count[j+1]=temp; } } return (count[3]-count[0]); } BOOL question9(struct answer* answer_set,int num){//第十題的命題判斷函式 if(num>=1048576||num<0){ printf("答案編號輸入錯誤\n"); return 0; } else if (answer_set[num].index[9]<97||answer_set[num].index[9]>100){ printf("答案選項輸入錯誤\n"); return 0; }//輸入檢查 if(answer_set[num].index[9]=='a'){//答案為a時 if(max_Minus_min(answer_set,num)==3) return 1; else return 0; } if(answer_set[num].index[9]=='b'){//答案為b時 if(max_Minus_min(answer_set,num)==2) return 1; else return 0; } if(answer_set[num].index[9]=='c'){//答案為c時 if(max_Minus_min(answer_set,num)==4) return 1; else return 0; } if(answer_set[num].index[9]=='d'){//答案為d時 if(max_Minus_min(answer_set,num)==1) return 1; else return 0; } } int p=0; void push(int *array,int num){ if (p<10){ array[p]=num; p++; } else printf("正確答案數量超過10個\n"); } int main(){ struct answer *answer_set= (struct answer*)malloc(1048576*sizeof(struct answer)); //宣告答案陣列,為1048576個組員(所有可能的答案)申請空間 init_answer_set(answer_set,0,1048575,0); int RightAnswers[10]; int num; int i; int bl[10]={0}; void printf_bl(int num){ int i; printf("第%d個答案的bl值是\n",num); for (i=0;i<10;i++){ printf("%d\t",bl[i]); } printf("\n"); } for(num=0;num<1048576;num++){ if(question0(answer_set,num)==0) continue; else if(question1(answer_set,num)==0) continue; else if(question2(answer_set,num)==0) continue; else if(question3(answer_set,num)==0) continue; else if(question4(answer_set,num)==0) continue; else if(question5(answer_set,num)==0) continue; else if(question6(answer_set,num)==0) continue; else if(question7(answer_set,num)==0) continue; else if(question8(answer_set,num)==0) continue; else if(question9(answer_set,num)==0) continue; else{ push(RightAnswers,num); printf("找到一個正確答案,編號是%d\n",num); // getchar(); } } for(i=0;i<p;i++){ printf_answer(answer_set,RightAnswers[i]); } }
最後執行,花費0.09秒得出答案:BCACACDABA。