http://chimf.bloghome.cn/posts/49570.html
先簡單介紹一下24點遊戲:
給出4個1-9之間的自然數,其中每個數字只能使用一次;任意使用 + - * / ( ) ,構造出一個運算式,使得最終結果為24,這就是常見的算24點的遊戲。比如兩道比較經典的題目:1,5,5,5和3,3,8,8,先自己試試,答案貼在文章最後^_^
此文所貼代碼均為面向過程的C(++)代碼,在VC6下編譯通過。
解決這個問題一般使用窮舉法,即窮舉4個整數所有可能的運算式,然後對錶達式求值。下面的兩種思路(三種演算法)均是基於窮舉法,各有優劣。
第一種思路:
把多元運算轉化為兩元運算,先從四個數中取出兩個數進行運算,然後把運算結果和第三個數進行運算,再把結果與第四個數進行運算。在求運算式的過程中,最難處理的就是對括弧的處理,而這種思路很好的避免了對括弧的處理。基於這種思路有兩種演算法:
第一種演算法:
(1) 將4個整數放入數組中,
(2) 在數組中取兩個數位排列,共有 P(4,2) 種排列。對每一個排列,
(2.1) 對 + - * / 每一個運算子,
(2.1.1) 根據此排列的兩個數字和運算子,計算結果,
(2.1.2) 改表數組:將此排列的兩個數字從數組中去除掉,將 2.1.1 計算的結果放入數組中,
(2.1.3) 對新的數組,重複步驟 2,
(2.1.4) 恢複數組:將此排列的兩個數字加入數組中,將 2.1.1 計算的結果從數組中去除掉。
可以看出,步驟2是一個遞迴函式。當數組中只剩下一個數位時候,這就是運算式的最終結果,此時遞迴結束。
這個是程式碼,原始碼為csdn 演算法論壇前版主海星所作,我修改了部分變數。此程式只能求出第一個解,無法求出全解。
引用內容:(略有修改,VC++ 2005下測試)#include<iostream><br />#include<string><br />#include<cmath><br />using namespace std;<br />const double PRECISION = 1E-6;<br />const int COUNT = 4;<br />const int RESULT = 24;<br />double number[COUNT]; //這裡一定要用double,看看第一題的答案就知道為什麼了<br />string expression[COUNT]; //儲存運算式<br />bool Test(int n){<br />//遞迴結束<br />if(1 == n){<br />if(fabs(number[0]-RESULT)<PRECISION){<br />// 避免輸出前後括弧<br />for (int i = 1; i < expression[0].length() - 1; i++)<br />{<br />cout<<expression[0][i];<br />}<br />cout<<endl;<br />return true;<br />}<br />else<br />return false;<br />}<br />//遞迴過程<br />for(int i=0;i<n;i++){<br />for(int j=i+1;j<n;j++){<br />double a,b;<br />string expa,expb;<br />a=number[i];<br />b=number[j];<br />// 刪除number[j]元素,用number[n-1]填補<br />number[j]=number[n-1];<br />expa=expression[i];<br />expb=expression[j];<br />// 刪除expression[j]元素,用expression[n-1]填補<br />expression[j]=expression[n-1];</p><p>// 加法<br />expression[i]='(' + expa + '+' + expb + ')';<br />number[i]=a+b;<br />if(Test(n-1))<br />return true;<br />//減號有兩種情況,a-b與b-a<br />expression[i]='('+expa+'-'+expb+')';<br />number[i]=a-b;<br />if(Test(n-1))<br />return true;<br />expression[i]='('+expb+'-'+expa+')';<br />number[i]=b-a;<br />if(Test(n-1))<br />return true;<br />// 乘法<br />expression[i]='('+expa+'*'+expb+')';<br />number[i]=a*b;<br />if(Test(n-1))<br />return true;<br />//除法也有兩種情況,a/b與b/a<br />if(b!=0){<br />expression[i]='('+expa+'/'+expb+')';<br />number[i]=a/b;<br />if(Test(n-1))<br />return true;<br />}<br />if(a!=0){<br />expression[i]='('+expb+'/'+expa+')';<br />number[i]=b/a;<br />if(Test(n-1))<br />return true;<br />}<br />//恢複數組<br />number[i]=a;<br />number[j]=b;<br />expression[i]=expa;<br />expression[j]=expb;<br />}<br />}<br />return false;<br />}<br />void main(void){<br />for(int i=0;i<COUNT;i++){<br />char buffer[20];<br />int x;<br />cin >> x;<br />number[i]=x;<br />_itoa_s(x,buffer,10);<br />expression[i]=buffer;<br />}<br />if(Test(COUNT))<br />cout << "Success" << endl;<br />else<br />cout << "Fail" << endl;<br />}<br />
附:
(5-(1/5))*5 = 24
8/(3-(8/3)) = 24