C語言實(shí)現(xiàn)經(jīng)典24點(diǎn)算法
本文實(shí)例為大家分享了C語言經(jīng)典24點(diǎn)算法的具體實(shí)現(xiàn)代碼,供大家參考,具體內(nèi)容如下
1、概述
給定4個整數(shù),其中每個數(shù)字只能使用一次;任意使用 + - * / ( ) ,構(gòu)造出一個表達(dá)式,使得最終結(jié)果為24,這就是常見的算24點(diǎn)的游戲。這方面的程序很多,一般都是窮舉求解。本文介紹一種典型的算24點(diǎn)的程序算法,并給出兩個具體的算24點(diǎn)的程序:一個是面向過程的C實(shí)現(xiàn),一個是面向?qū)ο蟮膉ava實(shí)現(xiàn)。
2、基本原理
基本原理是窮舉4個整數(shù)所有可能的表達(dá)式,然后對表達(dá)式求值。
表達(dá)式的定義: expression = (expression|number) operator (expression|number)
因?yàn)槟苁褂玫?種運(yùn)算符 + - * / 都是2元運(yùn)算符,所以本文中只考慮2元運(yùn)算符。2元運(yùn)算符接收兩個參數(shù),輸出計(jì)算結(jié)果,輸出的結(jié)果參與后續(xù)的計(jì)算。
由上所述,構(gòu)造所有可能的表達(dá)式的算法如下:
(1) 將4個整數(shù)放入數(shù)組中
(2) 在數(shù)組中取兩個數(shù)字的排列,共有 P(4,2) 種排列。對每一個排列,
(2.1) 對 + - * / 每一個運(yùn)算符,
(2.1.1) 根據(jù)此排列的兩個數(shù)字和運(yùn)算符,計(jì)算結(jié)果
(2.1.2) 改表數(shù)組:將此排列的兩個數(shù)字從數(shù)組中去除掉,將 2.1.1 計(jì)算的結(jié)果放入數(shù)組中
(2.1.3) 對新的數(shù)組,重復(fù)步驟 2
(2.1.4) 恢復(fù)數(shù)組:將此排列的兩個數(shù)字加入數(shù)組中,將 2.1.1 計(jì)算的結(jié)果從數(shù)組中去除掉
可見這是一個遞歸過程。步驟 2 就是遞歸函數(shù)。當(dāng)數(shù)組中只剩下一個數(shù)字的時候,這就是表達(dá)式的最終結(jié)果,此時遞歸結(jié)束。
在程序中,一定要注意遞歸的現(xiàn)場保護(hù)和恢復(fù),也就是遞歸調(diào)用之前與之后,現(xiàn)場狀態(tài)應(yīng)該保持一致。在上述算法中,遞歸現(xiàn)場就是指數(shù)組,2.1.2 改變數(shù)組以進(jìn)行下一層遞歸調(diào)用,2.1.3 則恢復(fù)數(shù)組,以確保當(dāng)前遞歸調(diào)用獲得下一個正確的排列。
括號 () 的作用只是改變運(yùn)算符的優(yōu)先級,也就是運(yùn)算符的計(jì)算順序。所以在以上算法中,無需考慮括號。括號只是在輸出時需加以考慮。
3、面向過程的C實(shí)現(xiàn)
這是 csdn 算法論壇前版主海星的代碼,程序非常簡練、精致:
#include
#include
#include
using namespace std;
const double PRECISION = 1E-6;
const int COUNT_OF_NUMBER = 4;
const int NUMBER_TO_BE_CAL = 24;
double number[COUNT_OF_NUMBER];
string expression[COUNT_OF_NUMBER];
bool Search(int n)
{
if (n == 1) {
if ( fabs(number[0] - NUMBER_TO_BE_CAL) < PRECISION ) {
cout << expression[0] << endl;
return true;
} else {
return false;
}
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
double a, b;
string expa, expb;
a = number[i];
b = number[j];
number[j] = number[n - 1];
expa = expression[i];
expb = expression[j];
expression[j] = expression[n - 1];
expression[i] = '(' + expa + '+' + expb + ')';
number[i] = a + b;
if ( Search(n - 1) ) return true;
expression[i] = '(' + expa + '-' + expb + ')';
number[i] = a - b;
if ( Search(n - 1) ) return true;
expression[i] = '(' + expb + '-' + expa + ')';
number[i] = b - a;
if ( Search(n - 1) ) return true;
expression[i] = '(' + expa + '*' + expb + ')';
number[i] = a * b;
if ( Search(n - 1) ) return true;
if (b != 0) {
expression[i] = '(' + expa + '/' + expb + ')';
number[i] = a / b;
if ( Search(n - 1) ) return true;
}
if (a != 0) {
expression[i] = '(' + expb + '/' + expa + ')';
number[i] = b / a;
if ( Search(n - 1) ) return true;
}
number[i] = a;
number[j] = b;
expression[i] = expa;
expression[j] = expb;
}
}
return false;
}
void main()
{
for (int i = 0; i < COUNT_OF_NUMBER; i++) {
char buffer[20];
int x;
cin >> x;
number[i] = x;
itoa(x, buffer, 10);
expression[i] = buffer;
}
if ( Search(COUNT_OF_NUMBER) ) {
cout << "Success." << endl;
} else {
cout << "Fail." << endl;
}
}
使用任一個 c++ 編譯器編譯即可。
這個程序的算法與 2、基本原理所述的算法基本相同。其中 bool Search(int n) 就是遞歸函數(shù),double number[] 就是數(shù)組。程序中比較重要的地方解釋如下:
(1) string expression[] 存放每一步產(chǎn)生的表達(dá)式,最后的輸出中要用到。expression[] 與 number[] 類似,也是遞歸調(diào)用的現(xiàn)場,必須在下一層遞歸調(diào)用前改變、在下一層遞歸調(diào)用后恢復(fù)。
(2) number[] 數(shù)組長度只有4。在 search() 中,每次取出兩個數(shù)后,使用局部變量 a, b 保存這兩個數(shù),同時數(shù)組中加入運(yùn)算結(jié)果,并調(diào)整數(shù)組使得有效的數(shù)字都排列在數(shù)組前面。在下一層遞歸調(diào)用后,利用局部變量 a, b 恢復(fù)整個數(shù)組。對 expression[] 的處理與 number[] 類似。
(3) 因?yàn)?+ * 滿足交換率而 - / 不滿足,所以程序中,從數(shù)組生成兩個數(shù)的排列,
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
其內(nèi)層循環(huán) j 是從 i+1 -> n,而非從 0->n ,因?yàn)閷τ诮粨Q率來說,兩個數(shù)字的順序是無所謂的。當(dāng)然,循環(huán)內(nèi)部對 - / 做了特殊處理,計(jì)算了 a-b b-a a/b b/a 四種情況。
(4) 此程序只求出第一個解。當(dāng)求出第一個解時,通過層層 return true 返回并輸出結(jié)果,然后程序結(jié)束。
(5) 以 double 來進(jìn)行求解,定義精度,用以判斷是否為 24 ??紤] (5-1/5)*5 這個表達(dá)式就知道這么做的原因了。
(6) 輸出時,為每個表達(dá)式都添加了括號。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:淺析C/C++ 中return *this和return this的區(qū)別
欄 目:C語言
本文標(biāo)題:C語言實(shí)現(xiàn)經(jīng)典24點(diǎn)算法
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/164.html
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)式函數(shù)庫
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對數(shù)怎么表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?


