程式設計之美讀書筆記22 1 16 24點遊戲

2021-05-23 05:27:12 字數 2923 閱讀 3272

程式設計之美讀書筆記

221.1624

點遊戲給定

4個數,能否只通過加減乘除計算得到

24?由於只有

4個數,弄個多重迴圈,就可以。如果要推廣到

n個數,有兩種思路:

①採用字首

/字尾表示式。相當於將

n個數用

n-1個括號括起來,其數目就是乙個

catlan

數。最多可得到

f(n) = (1/n * (2*n - 2)! / (n-1)! / (n-1)!) * n! * 4^(n-1) = 4^(n-1) * (2*n-2)! / (n-1)!

種表示式,當

n=4時,共可得到

7680種。②

從n個數中任意抽取

2個,進行計算最多有

6種結果,將計算結果放回去,再從剩下的

n-1個任取

2個,進行計算,如此反覆,直到只剩下

1個數。按這種演算法,共要處理表示式:

g(n)=(n*(n-1)/2*6) * ((n-1)*(n-2)/2*6) * ((n-2)*(n-3)/2*6) * (2*1/2*6) = n!*(n-1)!*3^(n-1)

當n=4

時,最多要處理

3888種。(

書上的**將這兩種思路混在一塊了。)

f(n) / g(n) = (4/3)^(n-1) * (2*n-2)! / n! / (n-1)! / (n-1)!

很明顯,當

n比較大時(比如n大於

8),會有

f(n) < g(n)

。比如:

f(10)/g(10)=0.178。從

f(n)

與g(n)

的比值,可以看出,這兩種解法都存在大量的不必要計算。當

n比較大時,思路

2的冗餘計算已經嚴重影響了效能。要如何減少這些不必要計算呢?

可以記錄得到某個計算結果時所進行操作。比如

: a、b、

c和d這

4個數取前

2個,進行加法計算得到

a+b,則記錄『

+』。另外,假設加減號的優先順序為

0,乘除號的優先順序為1。

a和b進行減

/除計算時,實際上得到

a-b與

b-a,

a/b與

b/a。

當取出2個數a

和b,進行計算,這兩個數上次的操作符有下面這幾種情況:

①都為空:

要計算6

個結果,即

a+b, a-b, b-a, a*b, a/b, b/a。②

只有乙個為空:假設:

a = a1 op1 a2

⑴ 一種剪枝方法是:

若op1

為減(除)號,則不進行加減(乘除)計算。

因為:(a-b)-c

可以轉為

a-(b+c)

,這兩個表示式只要計算乙個就可以。

⑵ 另一種剪枝方法:額外記錄每次計算最靠後的那個數的位置。比如位置順序:a、

b、c、

d,進行

a+c計算時,記錄了

c位置,再與數

b計算時,由於

b位置在

c位置前,不允許計算

(a+c) + b

和(a+c) – b

這樣就避免了表示式

a+b+c

和a-b+c

被重複計算。

③都不為空:

假設:a = a1 op1 a2

,b= b1 op2 b2

要計算的結果:

a op3 b =

(a1 op1 a2

)op3 (b1 op2 b2)

⑴ 如果

op1

和op2

的優先順序相同,那麼

op3

的優先順序不能與它們相同,若相同,則原來的表示式可以轉為

((a1 op4 a2) op5 b1) op6 b2

,因而沒必要對原來的表示式進行計算。比如

(m1+m2)

與(m3-m4)

之間只進行乘除計算,而不進行加減計算。

⑵ 如果

op1

和op2

的優先順序不同,那麼

op3

無論怎麼取,其優先順序都必會與其中乙個相同,則原表示式可以轉化

((c1 op4 c2) op5 c3) op6 c4

這種形式,因而該表示式沒必要計算。如

(m1+m2)

與(m3*m4)

,不進行任何計算。

總之:op1

與op2

優先順序不同時,不進行計算。

op1

與op2

優先順序相同時,進行計算的操作符優先順序不與它們相同。

要注意的是:剪枝不一定提高效能(在筆記

1.3

一摞烙餅的排序 中已經說明了這個問題

)。如果

n個數計算可得到

24,過多的避免冗餘計算,有可能嚴重降低效能。計算

n=6時,碰到乙個組合,僅使用了③的剪枝方法,得到結果時處理了四百個表示式,但再採用了②的第一種剪枝方法,處理的表示式達到五十三萬多。(也許②的第二種剪枝方法不存在這麼嚴重的問題。)與烙餅排序不同的是,烙餅排序總能找到乙個結果,而

n個數計算有可能無解。顯然在無解時,採用盡可能多的剪枝方法,必然會極大的提高效能。

另外,對於輸出表示式,書上的程式進行了大量的字串操作,實際上可以只記錄,每一步取出的兩個數的位置(即記錄i、

j值),在需要輸出時,再根據所記錄的位置,進行相應的字串操作就可以了。

書上給出的另一種解法,通過記錄中間結果來減少冗餘計算。在

n比較小時,對效能改進影響不會太大;

n較大時,中間結果需要多少記憶體?是否會出現物理記憶體不足,而使程式效能極其低下呢?

下面的**是個半成品:

《程式設計之美》讀書筆記

程式設計之美 讀書筆記 一 中國象棋將帥問題 程式設計之美 讀書筆記 二 求二進位制數中1的個數 擴充套件問題 程式設計之美 讀書筆記 三 一摞烙餅的排序問題 程式設計之美 讀書筆記 四 買書折扣問題的貪心解法 程式設計之美 讀書筆記 五 飲料 問題 程式設計之美 讀書筆記 六 連連看遊戲設計 程式...

《程式設計之美》讀書筆記集錦

程式設計之美 讀書筆記 一 中國象棋將帥問題 程式設計之美 讀書筆記 二 求二進位制數中1的個數 擴充套件問題 程式設計之美 讀書筆記 三 一摞烙餅的排序問題 程式設計之美 讀書筆記 四 買書折扣問題的貪心解法 程式設計之美 讀書筆記 五 飲料 問題 程式設計之美 讀書筆記 六 連連看遊戲設計 程式...

《程式設計之美》讀書筆記集錦

程式設計之美 讀書筆記 一 中國象棋將帥問題 程式設計之美 讀書筆記 二 求二進位制數中1的個數 擴充套件問題 程式設計之美 讀書筆記 三 一摞烙餅的排序問題 程式設計之美 讀書筆記 四 買書折扣問題的貪心解法 程式設計之美 讀書筆記 五 飲料 問題 程式設計之美 讀書筆記 六 連連看遊戲設計 程式...