快算24 回溯

2021-10-05 14:58:11 字數 2632 閱讀 3266

成績

10開啟時間

2023年04月7日 星期二 08:55

折扣0.8

折扣時間

2023年05月1日 星期五 23:55

允許遲交

否關閉時間

2023年05月1日 星期五 23:55

一副牌,除了大小王之外還有52張,從1到13每個數目各有四張。要求設計乙個程式,對於任意給出52張牌中的四張,運用+-×÷四種運算來判斷能否每個數只能用一次,但不能不用,算出24來。注意,給出的4個數是無序的,可以新增括號。

測試輸入

期待的輸出

時間限制

記憶體限制

額外程序

測試用例 1

1 1 1 1↵

2 3 4 1↵

7 2 1 1↵

no↵yes↵

yes↵

1秒64m

0

首先大致列舉 4 位數字組合運算的所有可能情況,大致可以將導致結果不同的因素有:

四位數字的排列順序:如 2、3 、4、1 與  2、4、3、1

四位數字的運算順序(括號如何加):如(2 + 3) - (4 + 1) 與 (2 + 3) - 4 + 1

四位數字之間的運算(3個運算子):如 (2 + 3) - (4 + 1) 與 (2 + 3) - (4 - 1) 

粗略地算一下大概有理清楚如何將所有情況都搜尋到,主要考慮回溯法,剪枝不剪枝都沒關係了~

先看乙個小細節,通過觀察發現,其實第乙個因素(不同的排列順序)不同(2、3因素相同時)或許不會有影響,如:(2 + 3) - (4 + 1) 與 (3 + 2) - (1 + 4)。其實就是:

加、乘與前後順序無關,減、除與前後順序有關。 

分別考慮三種因素會使得回溯變得很複雜,而且上面也說明了1、2因素單獨列舉時會產生重複部分,故這裡考慮將1、2因素合併考慮,第3個因素單獨考慮。那麼,演算法的大概思路如下:

從四個數中選取兩個數進行運算,運算結果為x,此時還剩下三個數待運算(x與未參與運算的兩個數)

從三個數中選取兩個數進行運算,運算結果為x,此時還剩下兩個數待運算(x與未參與運算的乙個數)

選取剩下的兩個數進行運算,得到最終的結果y

若y=24,即這樣子選取的結果是可以的,輸出yes。否則重新選取(若全部都選取完都沒有找到結果為24,就要輸出no)

1、2因素合併考慮的部分:三次選取的過程就是對於整個1、2因素的合併,包含了所有的1、2因素不同而導致的情況。

3因素考慮的部分:對應於每次對於選取出的兩個數字(無序)進行運算的過程。但是注意,這裡不應該只列舉 4 種運算,而是 6 種!因為對於兩個數無序運算的所有結果,減法、除法應該列舉兩次!

這裡的實現巧妙地使用了兩個迴圈的巢狀 與 flag陣列標記 來模擬選取過程,做到了不重不漏。比較難理解的就是:迴圈變數 i、j分別代表尋找的兩個數,一定是未被標記的(也就是未被計算過的,否則會跳過該位的選取)。注意:這裡每次選出的兩個數字的運算結果,又儲存回 i 的 位置,繼續進行運算。而只有 j 位置會被標記。也就是取出兩個,儲存結果。

進入迴圈體後再對於兩個數枚舉 6 種運算。

(其實回溯演算法的每一層step的值就是對應本文 2 中列舉的演算法思路的步數。)

此題有點難理解,按照我的梳理好好消化一下**應該能很快想明白~下面貼出 ac **:

//

// created by a on 2020/4/29.

//#include #include #include #define dif 0.0000001

bool flag[5] = ; //標記該位是否被計算過

double num[5] = ; //每一位的值

bool calc24(int step)

for (int i = 1; i <= 4; i++)

if (!flag[i])

for (int j = i + 1; j <= 4; j++)

num[i] = temp2 - temp1;

if (calc24(step + 1))

return true;

if (temp1 != 0)

/* 還原,便於回溯 */

num[i] = temp1;

flag[j] = false;}}

return false; //一直沒有出口

}int main()

}

flag陣列每次迴圈內一定要初始化!不然會保留上次的結果導致本次的錯誤

記得在列舉兩種除法運算時跳過除數為 0  的情況!否則會re

在step = 4 即判定結果的時候,一定是對結果位判斷是否為24(此時只有結果位的flag為false),否則可能中間結果出現了24也會被判斷成yes。不明白這一點的,可以試試這個用例:3 4 2 3,正確結果為no。我當時就是因為這一點wa了最後乙個用例

num陣列應該用double儲存,因為中間會儲存中間值,會出現小數

對於結果是否等於24的判定是浮點數的判定,因為浮點數的運算是無法完全精準的,要排除一些誤差。故不要直接與24判等,而是與24的差值較小即可。

如有幫助,不妨點讚~

39 回溯演算法

var res 全域性遍歷,下標表示行,值表示queen所在列 cal8queens 0 遞迴函式,求每行的queen function cal8queens row for let col 0 col 8 col 判斷棋子放在 row,col 位置,是否正確 function isok row,c...

演算法8 回溯

理論基礎 回溯法是一種組織搜尋的一般技術,有 通用的解題法 之稱,用它可以系統的搜尋乙個問題的所有解或任一解。有許多問題,當需要找出它的解集或者要求回答什麼解是滿足某些約束條件的最佳解時,往往要使用回溯法。可以系統地搜尋乙個問題的所有解或任意解,既有系統性又有跳躍性。回溯法的基本做法是搜尋,或是一種...

實驗五 回溯法

實驗 五 回溯法 一 實驗目的與要求 1 通過回溯法的示例程式理解回溯法的基本思想 2 運用回溯法解決實際問題進一步加深對回溯法的理解和運用 二 實驗內容 1 分析並掌握 符號三角 問題的回溯法求解方法 2 分析並掌握 n皇后 問題的回溯演算法求解方法 3 練習使用回溯法求解 整數變換 等問題。三 ...