Ⅰ C語言24點的演算法
下面是我自己寫的一個程序:
我的解法是把這個問題分解成了兩個子問題,首先求出4個數字的無重復全排列,放到一個數組裡面,再對沒一個排列情況,從頭到尾窮舉所有的四則運算情況。注意到除法是特殊的,我用x/y表示x除以y,用x|y表示x分之y。注意到,如果窮舉的解得到-24的話,只需要把有減法的地方調換一下順序就可以了,代碼如下
/***********************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int index[4]={0,1,2,3};//used to generate subscription collection
int sub[4]; //used in p() only
float f[4]={8.0f,3.0f,3.0f,8.0f};//the 24 point numbers
float fs[24][4];//all possible permutaions of f
float tmp[4]; //used for buf
int g_number=0; //number of permutations
float RES[4];
char op[3];
void p(int idx){//求全排列的函數
if(idx==4){
for(int i=0;i<4;++i){tmp[i]=f[sub[i]];}
for(int g=0;g<g_number;++g){if(memcmp(fs[g],tmp,sizeof(float)*4)==0)return;}
for(int i=0;i<4;++i){fs[g_number][i]=f[sub[i]];}
g_number++;
return;
}
for(int i=0;i<4;++i){//make subscription collections
bool pflag=false;
for(int j=0;j<idx;++j){if(sub[j]==i)pflag=true;}
if(pflag==true)continue;
sub[idx]=index[i];
p(idx+1);
}
}
void solve(int L){//對某個排列,遞歸求所有四則運算的結果,找到就退出
if(L==3){
if(fabs(fabs(RES[L])-24.0f)<0.01f){
printf("Found solution,RES=%f,((%d%c%d)%c%d)%c%d\n",RES[L],
(int)f[0],op[0],
(int)f[1],op[1],
(int)f[2],op[2],
(int)f[3]);
exit(0);
}
return;
}
for(int j=0;j<5;++j){//j judges for operators
if(j==0){RES[L+1]=RES[L]+tmp[L+1];op[L]='+';solve(L+1);}
if(j==1){RES[L+1]=RES[L]-tmp[L+1];op[L]='-';solve(L+1);}
if(j==2){RES[L+1]=RES[L]*tmp[L+1];op[L]='*';solve(L+1);}
if(j==3&&tmp[L+1]!=0)
{RES[L+1]=RES[L]/tmp[L+1];op[L]='/';solve(L+1);}
if(j==4&&RES[L+1]!=0)
{RES[L+1]=tmp[L+1]/RES[L];op[L]='|';solve(L+1);}
}
}
int main(int argc,char* argv[]){//should avoid 0
f[0]=atoi(argv[1]);
f[1]=atoi(argv[2]);
f[2]=atoi(argv[3]);
f[3]=atoi(argv[4]);
p(0);
for(int i=0;i<g_number;++i){
memcpy(tmp,fs[i],sizeof(float)*4);
RES[0]=tmp[0];
for(int t=0;t<4;++t){ printf("%d,",(int)tmp[t]); }
printf("\n");
solve(0);
}
printf("Found no solution :( \n");
return 0;
}
----------編譯運行,運行時的參數就是4個數字
g++ p.cpp && ./a.out 1 5 5 5
1,5,5,5,
Found solution,RES=-24.000000,((1/5)-5)*5
g++ p.cpp && ./a.out 8 3 3 8
8,3,3,8,
Found solution,RES=-24.000006,((8/3)-3)|8
上面這個解寫出來就是
8
--------- = 24
3-(8/3)
主程序為了簡化,省去了對輸入的檢查,樓主可以自己添加。
Ⅱ 求高手用c++解決二十四點的問題,具體如下
24點演算法分析
很久沒有研究程序了,慚愧中。。。這個夏天大致地翻了一下微軟亞洲研究院出的《編程之美》,很喜歡這本書的風格,裡面很多題目都很有意思。書中主要突出的是一個「巧」字,最關鍵的,就是從變化中尋找不變的規律。 這次說的問題其實也很簡單,給四個數,寫一個程序輸出算24點的結果,如果沒有就輸出「No Answer」。但是如果用我們自己算24點的思維來寫程序是不行的,因為那屬於一種「湊」的方法,有碰巧和經驗的成分。計算機能做的,就是通過一種固定的方式來找尋結果。如果沒有一般性的所謂「固定」方式,那麼只有通過遍歷和窮舉來解決問題。這樣的方法下誕生了很多所謂的NP難問題,如果原始數據規模比較大就要花很長的時間來得到結果。
24點這個問題最直接的方法就是,列舉四個數所有的排列組合,加上各種運算符以及括弧,所有的情況經過處理之後可以得到一個包含所有計算結果和計算式的列表,從其中尋找24的影蹤就可以了。如果不計計算結果重復的情況,最終的結果有7680種,數據量還是有點大,因此這個演算法需要進一步的優化。例如,考慮到加法和乘法的交換律,如果遇到相應的情況只計算一種,對於另一種直接返回。這樣的剪枝處理可以減少不少的運算。
不過我用的是書中的另一種思路,採用了劃分的思想。具體的演算法是:
如果A是一個數組,定義f(A)為數組中的所有數經過四則運算所能得到的結果的集合。對於A中元素個數大於1的情況,可以將A分拆成兩個集合,定義運算 Fork(A,B)為f(A)和f(B)中各取一個元素的四則運算得到的所有的結果的集合。這樣,如果列舉出集合A所有的拆分情況,那麼所有Fork結果的並集就是f(A)的結果。
對於24點的情況,因為數組A有4個數,因此將其用各種方法拆分即可得到最終的f(A),然後查詢其中是否存在元素24即可得到有解或者無解的判斷。
需要說明的有幾點:
1.這個問題表面上需要採用遞歸的演算法,即如果只有一個元素那麼直接返回,否則將問題轉化為多個f的計算,而每個f的計算又要經過轉化,層層遞歸,直至只有一個元素的情況。但是,不要忘了遞歸的方法一般都是針對回溯次數不確定的問題。例如漢諾塔問題,只有一個盤子的情況和64個盤子的情況,回溯次數截然不同,千差萬別;但是對於24點,因為只有4個數,實際上分拆的可能性是固定的,就那麼有限種情況。遞歸演算法的思路是從樹的根部往下遍歷,而且一般不知道樹的大小和規模。而對於24點問題,這棵樹的大小固定,完全可以從樹的葉子著手,從葉子向根步進,從而得到最終的結果。
2.分拆有一定的技巧,最合適的方法是通過位運算。比如一種分拆方法是{a1,a2},{a3,a4},那麼寫做1100和0011。這種方法的好處在於,比如要判斷1000是不是1100的一個子集,只需要將兩者做與運算,最後的結果如果還等於1100則表明確實是子集,同時分拆的另一個結果便是兩者的差。這樣至多隻需要比較 10多次就可以列舉出每個集合所有的分拆情況,比較巧妙的方法。同時,位運算的速度也很快,不會對計算的時間有較大的影響。
3.這個方法的缺點在於,最終得到的只是一個無解或者有解的判斷,並沒有輸出表達式。
所以我對這個演算法進行了一定的改進,使之能輸出表達式。
首先要考慮的,也是最重要的,是這個程序的數據結構。最終的目的自然是為了達到最少的時間復雜度。由於上述方法中f函數返回的是「集合」,因此不存在重復的元素。這樣的情況下,哈希表自然是首選的數據結構。
為了記錄表達式,需要引入另一套數據結構。每一個計算的結果都必須和一個表達式對應。這樣,當最終查詢到一個計算結果為24的時候,只需查找相應的表達式就可以得到結果。
這里就產生了沖突。哈希表的特點是存放是亂序的,也就是說,如果只採用一個哈希表存放計算結果,用一個vector存放表達式,那麼無法產生對應關系。
因此,有兩種方案:
第一種方案比較節省存儲空間,將計算結果和表達式分別存在兩個vector中,由於兩者都是有序的集合類,因此可以在插入數據的時候令各自的下標對應,這樣就可以方便地得到對應關系。但是,這樣做的後果是,在插入新數據的時候需要在vector中查找是否已經存在這個計算結果,如果已有則不必插入。 vector的查找是窮舉式的,效率比較低,尤其是當vector比較大的時候將很大程度上影響計算的效率。但如果不進行查找,勢必會計算很多沒有意義的重復結果,這樣就失去了這個演算法的意義了。
第二種方案在第一種方案的基礎上將計算結果多存一份哈希表數據。這樣做增加了存儲空間,但是在時間上的優勢是顯而易見的。在插入的時候,通過查找哈希表來決定是否已經存在這個結果,由於哈希表的查找效率很高,因此這一步不會對這個程序造成時間上的瓶頸。如果不存在,那麼同時在哈希表和兩個vector中同時插入數據即可。計算結果和表達式的對應關系依然存在,同時查找的效率也大大提高,整個程序的時間復雜度大大降低。這是典型的空間換時間的方法。
寫演算法我首選的語言還是c++,但是很慚愧c++的HashTable我不會用,因此用java寫了一個版本,還算比較成功,能輸出最終的結果。在寫程序前我寫了一個小程序來測試java的HashSet和ArrayList的查找效率,結果很令人驚訝。在10000次查詢中,HashSet所用時間為0ms,而ArrayList則用了1300多ms,看來這個效率完全不是一個數量級上的。因此我採用了上述的第二種方案,最終的效果還不錯。
曾經有人問過我5,5,5,1怎麼算24點,當時想了很久都沒想出來。現在用這個程序可以很輕松地算出5*(5-1/5)=24。看來這個程序可以輸出一些大家想不到的結果,很強大把。類似的例子還有很多,比如3,3,7,7等等。總之呢,優化了的窮舉法(我這個程序實際上還是一種變相的窮舉)是一種很不錯的解決問題的思路,值得採用!
過幾天就開學了。也許每年的開學前才有時間去研究下這種問題,等到開學之後就基本沒什麼時間了。嗯,好好工作把,也願今年能開個好題,明年好好做畢設。Good luck。
PS:昨天經同學提醒才發現有更好的解決方法。主要是因為好久沒用,把java的HashMap給忘了。這個數據結構用在這里正合適,也就是說不用兩個HashSet加兩個ArrayList解決了,直接存在一個HashMap裡面就可以。
具體的做法是:把計算結果存在map的key中,而表達式存在map的value中,問題徹底解決。map中key的查找效率是很高的,同時插入也很快;當找到一個計算結果為24的時候直接根據這個key去尋找相應的value即可得到完美的答案,同時HashMap也保證了每個計算結果只保留一個表達式,避免了重復。
我做了一下性能測試,總的來這個改進後的版本效率比以前的版本略有提高,但是最關鍵的是大大減少了空間的存儲,因此也算是對程序進行的大優化把我想。這兩天看這個帖子似乎看的人比較多哈,也願我的想法能給大家一些啟發。
Ⅲ 6.6.9.10算24點怎麼算
算24點的技巧:有基本算式法,特性求解法,倍數法,巧用分數法,具體解法如下:
1、基本算式法
利用2*12=24,3*8=24,4*6=24求解。一般情況下,先要看四張牌中是否有2,3,4,6,8,Q,如果有,考慮用乘法,將剩餘的三個數湊成對應數。如3,3,6,10可組成(10-6/3)*3=24。如果沒有2,3,4,6,8,Q,看是否能先把兩個數湊成其中之一,再求解24。
2、特性求解法
1)利用0、11的運算特性求解。如(3,4,4,8)可組成3*8+4-4=24。
2)如果有兩個相同的6,剩下的只要能湊成2,3,4,5都能算出24,比如6,6,3可以3*6+6=24。同理,如果有兩個相同的8,剩下的只要能湊成2,3,4就能算出24。
如(2,5,8,8),(5-2)*8=24,多一個8,可以用乘法的分配律消去8,將算式改為5*8-2*8,將多餘的8消去;如果有兩個相同的Q,剩下的只要能湊成1,2,3就能算出24,如(9,J,Q,Q)可以12*11-12*9=24。
3、倍數法
利用24的倍數求解2*24=48,3*24=72,4*24=96,5*24=120,6*24=144想辦法去湊48,72,96,120,144來求解。在具體的運算過程中,先將數乘得很大,最後再除以一個數得24。
4、巧用分數法
利用24的分數求解。先將數算成分數或小數,最後乘以一個數得24。用一個數除以一個分數,相當於乘以這個數的倒數,最後得24。
24點的口訣為見3湊8,見4湊6,見2湊12等等。
稍微特殊點的規律:2乘10+4,15+9,21+3,14+10等。
(3)24點遞歸演算法輸出結果擴展閱讀:
「算24點」作為一種撲克牌智力游戲,還應注意計算中的技巧問題。計算時,我們不可能把牌面上的4個數的不同組合形式——去試,更不能瞎碰亂湊。這里向大家介紹幾種常用的、便於學習掌握的方法:
1.利用3×8=24、4×6=24求解。
把牌面上的四個數想辦法湊成3和8、4和6,再相乘求解。如3、3、6、10可組成(10—6÷3)×3=24等。又如2、3、3、7可組成(7+3—2)×3=24等。實踐證明,這種方法是利用率最大、命中率最高的一種方法。
2.利用0、11的運算特性求解。
如3、4、4、8可組成3×8+4—4=24等。又如4、5、J、K可組成11×(5—4)+13=24等。
3.在有解的牌組中,用得最為廣泛的是以下六種解法:(我們用a、b、c、d表示牌面上的四個數)
①(a—b)×(c+d)
如(10—4)×(2+2)=24等。
②(a+b)÷c×d
如(10+2)÷2×4=24等。
③(a-b÷c)×d
如(3—2÷2)×12=24等。
④(a+b-c)×d
如(9+5—2)×2=24等。
⑤a×b+c—d
如11×3+l—10=24等。
⑥(a-b)×c+d
如(4—l)×6+6=24等。
游戲時,同學們不妨按照上述方法試一試。
需要說明的是:經計算機准確計算,一副牌(52張)中,任意抽取4張可有1820種不同組合,其中有458個牌組算不出24點,如A、A、A、5。
經典24點
4
4
10
10
這個難點在於先要算出一個很大的數,就是100,然後再通過減4,除4就可以得到24點:(10×10-4)÷4=24。
6
9
9
10
這個也要先算大數90,然後除6,再加9即可得24點:9×10÷6+9=24。
2
2
2
9
這個並不難,只是數字比較好玩,包含了3個2,其計算方法為:(2+9)×2+2=24。
1、概述
給定4個整數,其中每個數字只能使用一次;任意使用 + - * / ( ) ,構造出一個表達式,使得最終結果為24,這就是常見的算24點的游戲。這方面的程序很多,一般都是窮舉求解。本文介紹一種典型的算24點的程序演算法,並給出兩個具體的算24點的程序:一個是面向過程的C實現,一個是面向對象的java實現。
2、基本原理
基本原理是窮舉4個整數所有可能的表達式,然後對表達式求值。
表達式的定義: expression = (expression|number) operator (expression|number)
因為能使用的4種運算符 + - * / 都是2元運算符,所以本文中只考慮2元運算符。2元運算符接收兩個參數,輸出計算結果,輸出的結果參與後續的計算。
由上所述,構造所有可能的表達式的演算法如下:
(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 就是遞歸函數。當數組中只剩下一個數字的時候,這就是表達式的最終結果,此時遞歸結束。
在程序中,一定要注意遞歸的現場保護和恢復,也就是遞歸調用之前與之後,現場狀態應該保持一致。在上述演算法中,遞歸現場就是指數組,2.1.2 改變數組以進行下一層遞歸調用,2.1.3 則恢復數組,以確保當前遞歸調用獲得下一個正確的排列。
括弧 () 的作用只是改變運算符的優先順序,也就是運算符的計算順序。所以在以上演算法中,無需考慮括弧。括弧只是在輸出時需加以考慮。
Ⅳ 24點游戲演算法
看了N個24點的源碼了,雖然都能正確的得到結果,不過從效率和智能上來說都很垃圾。(國內的程序員,大多也就是在源碼基礎上改改而已,這也是企業追逐經濟利益的趨勢。真正寫底層演算法的高手就沒多少了。。。如果A*,8皇後和跳馬的演算法對你來說沒什麼難度,可以嘗試寫下。很多人應該可以略過看下面的內容了,或者只看不思考,免得傷腦筋)。 這些演算法的通病,也正是我目前想解決的問題是:1 效率性把24點擴展一下,就是要寫一個函數。function fun(arr:Array,num):Array{ //arr參數為[a,b,c,d,e....] //N個數字,在24點游戲里,為[a,b,c,d] 4個數 //num //要匹配的結果 24點游戲里,num=24 return Array //輸出結果存在數組里,如["(3+3)*(2+2)","(3*2+2)*3".........]}如果是N個數字的計算,用N來計算程序的復雜度。那麼24點的很多演算法是屬於窮舉排列,無法擴展,並且重復計算量很多。沒效率可言2 結果的正確性這個也能說明為什麼連把公式窮舉出來,作為類似索引表的這樣典型空間換時間的方法,效率還是很低。這里還涉及到一點智能問題。
AI很難識別相同的運算。
如 a+b+c+d 和 a+c+b+d 按游戲規則來說屬於同種方法 但是在很多方法里,會得出重復的,如同時會輸出 ((a+b)+c)*d 和 ((a+c)+b)*d這樣同樣的公式。在我們玩24點撲克游戲時,這點明顯是不允許的。雖然24點這游戲並不是那麼嚴謹,但是有這樣的潛規則 在別人講他的演算法時,如果你馬上能想出同樣能算出24的不同類的方法,可以視為平手 如 2*4*(4-1) 和 (4+4)*(2+1) 可以視為不同的演算法。 特殊情況,當牌有點數相同的,花色不同時, 相同點數的位置替代,也應屬於同類運算,但是沒有一個代碼能夠識別這些的。 另外(8-(1+3))*6 和 (8-1-3)*6 理應屬於同種演算法。在程序中理應執行一遍,並且也只屬於(8-1-3)*6這種括弧數較少的公式才合理。 程序一次是只能計算兩個數的運算的。用遞歸回溯的思路,可以方便的遍歷所有的執行順序和符號組合。但是實際寫起來,在程序中,用條件判斷,剔除種種不必要的運算和生成簡捷正確的公式,難度非常大。另外就是遞歸的層級相當多,代碼設計難度也很大。 這個程序執行所費的時間,花在公式上的存儲讀取時間和條件判斷所花費的時間也是相當可觀的。3 智能性 還是回到24點來說了。擬人的思路。 當我們玩24點的游戲,很多時候,大家都不願意多看,馬上要求換牌。比如說A,A,2,2。在程序里可以這樣解釋,if(a*b*c*d<24){return} 牌太小了不可能有計算結果。 這時我們換了一張牌,結果大家都搶著報自己的答案了。為什麼能這么快呢?這和人工智慧里的學習記憶機制掛點鉤。人算時,並不會像通常的程序那樣去排列組合,直到得到滿意的結果為止。而是有很多優先的成分。比如說4張牌裡面,有一張牌是3,那麼,我們馬上會想到的是把其它3張牌組合成8。而如果裡面有張牌是4,我們會想到把其它3張牌組合成6。而且24點這游戲一般兩人玩,手動出牌也很難保證4張牌同時出。不同人的注意力也集中在不同地方。就生成了一個優先度的問題。 如上所訴,那麼在計算24點的程序里,如果a,b,c,d裡面,有數字=2,3,4,6,8,12這樣的12的因數在裡面,我們一般應該將這樣的數字放在最後去計算,優先組合其它的3個數字。如果數字在數組的位置和優先計算有關系的話,即是 for(var i in arr){ if(arr[i]==24的因數){ arr.push(arr.splice(i,1)) } } 如果要換其中某一張牌時,這時我們其實已經將其他3張牌的種種排列組合已經計算好了。只能與換的那種牌組合了。如果其他3張牌組合好了與第4張牌在一起並不能得到結果,那麼也並不代表無解。只是這種方法行不通。那麼應該拋棄這樣的組合方式,並重新計算(從效率上來說,等同於這樣的演算法不需要再計算,程序的表達上,這點也較有難度)。 人腦計算時,如果4張牌裡面有相同的牌的話, 如果相同的牌不是24的因數,通常是優先把這樣的牌給計算掉,假設4張牌為[a1,b1,c,d](後接數字,數字相同的代表數值相等),那麼一般會先這樣拆 (a1?c)?(b1?d) ,把相同的牌盡量和其他的牌組合,生成24的因數。如 5,5,3,2 這樣的牌,我們會馬上反映出 5+3=8 5-2=3 3*8=24,那麼換成程序來說,4張牌的優先順序可能為[a1,c,b1,d],當a1,c經過計算得到新值e時,排列為[b1,d,e] 如果相同的牌是24的因數。那麼我們可能會保留一個,並計算其他3張能否湊成另一個需要的因數。如牌8,8,2,3 我們會優先計算 8*(8-2-2)。而程序上來說,4個數的優先程度是[a1,c,d,b1]上面只分析了部分常見情況,細分下來非常多,並且在程序里實現起來有點難度。不過如果分得很細了。條件判斷所用的時間視為0。而每次擬人的計算過程用setInterval(時間周期模擬人腦的一個計算周期),而不是簡單的for來算的話。可能那個24點的程序就很完善了。輸入一些參數,設置能模擬出不同的人在牌放置的位置時,計算所用的時間。如果下一次的4張牌剛好和上盤的4張牌一樣或重復了3張優先計算的牌,就會像人一樣馬上靠回憶而不是計算得出結果。 24點的撲克游戲,一個很簡單的游戲,如果想復雜了,也是個不得了的東西。
這樣可以么?
Ⅳ 各位大神! 4個數遞歸法求24點 不要用窮舉做 請用C 做 需要有詳細的註解,謝謝了 有必要可以追分~~~
具體詳細的註解我就不寫了,主要原理是這樣的
首先是通過四個數經過四則運算得到24,先取出第一個數跟24進行四則運算,獲得的四個結果就是剩下三個數經過四則運算需要得到的,以此類推知道最後一個數查看是否是你想要的,這樣通過遞歸法實現便可以求出結果
這里用到一個全排列演算法你可以自己看一下
具體詳細的註解我就不寫了,主要原理是這樣的
首先是通過四個數經過四則運算得到24,先取出第一個數跟24進行四則運算,獲得的四個結果就是剩下三個數經過四則運算需要得到的,以此類推知道最後一個數查看是否是你想要的,這樣通過遞歸法實現便可以求出結果
這里用到一個全排列演算法你可以自己看一下
代碼不知道為什麼貼不上了,總提示對不起!您的提問(回答)中包含不適合發表的內容,請修改後再提交 你看看能不能通過別的方法給你
Ⅵ C語言算24點
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char op[3], o[5]="+-*/";
float n[4], on[10];
int used[4] = {0}, top=0, tp=0, x;
void chk(float k);
void search24(int d);
float calc(float n1, float n2, char o);
void make(int i, float p, float q, char o, int d);
int main( void )
{
printf("please input 4 card number: ");
scanf("%f%f%f%f", &n[0], &n[1], &n[2], &n[3]);
search24(0);
printf("No answer. ");
return 0;
}
void chk(float k)
{
if( (tp != 3) || ( fabs(k-24.0) > 0.000001 )) //沒有用完3個運算符或者結果不為24就退出.
return;
for(x=0; x<5; x+=2) //這樣設計是為了使3個選中的符號都可以得到輸出.
printf("%g%c%g=%g ", on[x], op[x/2], on[x+1], //分析得到的.
calc(on[x], on[x+1], op[x/2]));
system("pause");
exit(0);
}
float calc(float n1, float n2, char o)
{
switch(o){
case '+': return (n1+n2);
case '-': return (n1-n2);
case '*': return (n1*n2);
case '/': return (n1/n2);
default: exit(0);
}
}
void make(int i, float p, float q, char o, int d)
{
if(fabs(q)>0.000001 || o!='/') //除數不為0,或者為0的時候不能為除數.
n[i] = calc(p, q, o);
op[tp++] = o;
chk(n[i]);
search24(d+1);
tp--; //因為是全是全局變數,所以在做試驗性的循環遞歸問題時,如果失敗,要在遞歸函數後面重新恢復回原來的值
}
void search24(int d)
{
int i, j, k;
float p, q;
if(d>=3) //控制遞歸深度,就是運算符的輸出個數.
return;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
if( (i!=j)&& (used[i]+used[j] == 0) ) //i!=j是防止重復,(used[i]+used[j] == 0)是防止又再匹配已經用過的j,
//但是i可以新來.
{
used[j] = 1; //j得到匹配之後,賦值為1,表示已經使用
p=n[i];
q=n[j];
on[top++] = p;
on[top++] = q;
for(k=0; k<4; k++) //運算符的循環試用.
make(i, p, q, o[k], d);
n[i] = p; //因為是全是全局變數,所以在做試驗性的循環遞歸問題時,
used[j] = 0; //如果失敗,要在遞歸函數後面重新恢復回原來的值
top -= 2; //
}
}
出處:http://blog.sina.com.cn/s/blog_491de9d60100d5er.html
Ⅶ 24點的演算法問題
這個問題實際上是一個編程問題,而不是計算問題。
可能您需要大量的時間來編寫這個演算法,但在計算中,可以獲得時間精簡。
比如:2 3 5 1
在標准24點程序中,試探2*5=10後,需求值為2.4或14,但是3+1隻能達到4(在這個問題中,明顯乘法所得值較大;在出現1時加法所得值較大),不可能更多,所以不用試探3和1的四則運算就可以舍棄2*5的計演算法。
在編程中,您當然必須耗費大量的腦力來窮舉,但是您可以讓計算機繞過一些明顯的死路,這樣可以用選擇比較來大大縮短計算的時間。
不要問我標准演算法,我只想提供思路。