一,概述
二十四點是一種益智遊戲,它能在遊戲中鍛鍊人們的心算,它往往要求人們將四個數字進行加減乘除(允許使用括號)求得二十四。然後將四個數字的計算公式表示出來。
二,中綴表示式求解
最直接的方法就是採用窮舉法,遊戲中可用的運算子只有四種,四個數字每個只能使用一次。
1)不考慮括號情況
4個數全排列:4!=24種
需要三個運算子,且運算子可以重複:4*4*4=64
總計:1536
2)考慮括號(是個難點)
自己想的加括號:四個數有五種加括號方式: (ab)cd 、ab(cd)、a(bc)d 、a((bc)d) 、(ab)(cd)、a(b(cd))
錯誤點:這裡新增括號的時候,需要把四個數都看成相乘。需要加兩個括號來列舉比較直觀
ab(cd) = (ab)(cd)
改正後:((ab)c)d 、
(ab)(cd)、 (a(bc))d 、a((bc)d) 、a(b(cd))
四個運算數五種不同加括號方式的由來。這是乙個經典的catalan數問題。
這個經典catalan數問題在組合數學教材上都能找到。原題目是:n 個數相乘, 不改變它們的位置, 只用括號表示不同的相乘順序,令g(n)表示這種條件下構成不同乘積的方法數,令c(n)表示第n個catalan數。則有g(n)=c(n-1)。前幾個catalan數為:c(0)=1,c(1)=1,c(2)=2,c(3)=5,c(4)=14,c(5)=42。所以g(4)=c(3)=5。
根據catalan數的計算公式,有g(4)=g(1)g(3)+g(2)g(2)+g(3)g(1)。
catalan數的計算公式也同時提供了構造答案的方法。對於4個數,中間有3個位置,可以在任何乙個位置一分為二,被分開的兩半各自的加括號方案再拼湊起來就得到一種4個數的加括號方案:
乙個數時:(a),一種
兩個數:g(2)=g(1)g(1),所以是(a)(b)=(ab),一種
三個數:g(3)=g(1)g(2)+g(2)g(1)=(a)(bc)+(ab)(c),兩種
四個數:g(4)=g(1)g(3)+g(2)g(2)+g(3)g(1)
=(a)[(b)(cd)+(bc)(d)]+(ab)(cd)+[(a)(bc)+(ab)(c)](d)
=a(b(cd)) + a((bc)d) + (ab)(cd) + (a(bc))d + ((ab)c)d
共有五種。於是寫**列舉這五種加括號的方式即可。這種方法只是一種能得到正確答案的方法,擴充套件性和效率都極差。而且生成的表示式中也有冗餘括號。
#include #include using namespace std;
const double threshold = 1e-6;
const int cardsnumber = 4;
const int resultvalue = 24;
double number[cardsnumber];
string result[cardsnumber];
bool pointsgame(int n)
else
}for(int i = 0; i < n; i++)//第乙個數(計算時被兩個數結果替換)
if(a != 0)
number[i] = a;//將本次迴圈的結果消除,繼續測試下一對數
number[j] = b;
result[i] = expa;
result[j] = expb;}}
return false;
}int main()
if(pointsgame(cardsnumber))
else
}
三,分支限界法求解
#include #include #include #include using namespace std;
#define n 4 // 4張牌,可變
#define res 24 // 運算結果為24,可變
#define eps 1e-6
struct elem
elem(double r, char* i):res(r),info(i){}
double res; // 運算出的資料
string info; // 運算的過程
bool operator<(const elem& e) const };
int a[n]; // 記錄n個資料
// 用二進位制數來表示集合和子集的概念,0110表示集合包含第2,3個數
setvset[1<& fork(int m)
for (int i=1; i<=m/2; i++)
if ((i&m) == i)
if (abs(cit1->res)>eps)
}} return vset[m];
}int main()
}
程式設計之美之24點遊戲
關於程式設計之美24點遊戲的求解 思想很簡單,把array i 和array i 1 求加減乘除等運算,然後將值寫入array i 1 不難發現是乙個遞迴子過程,不難寫,如下 include include using namespace std int array string arraystr ...
程式設計之美讀書筆記22 1 16 24點遊戲
程式設計之美讀書筆記 221.1624 點遊戲給定 4個數,能否只通過加減乘除計算得到 24?由於只有 4個數,弄個多重迴圈,就可以。如果要推廣到 n個數,有兩種思路 採用字首 字尾表示式。相當於將 n個數用 n 1個括號括起來,其數目就是乙個 catlan 數。最多可得到 f n 1 n 2 n ...
程式設計之美2 4 求1的個數
推薦 從1到n的所有數中,1出現的次數 例如 f 2 1,因為就有乙個1,f 13 6,有1,10,11,12,13,1一共出現6次 include include using namespace std void fun int n ifactor 10 cout 2 擴充套件問題 同之前問題1的...