C程序設計筆記---枚舉算法策略

枚舉法,又稱窮舉法,個人理解就是程序運行狀態是可以別遍歷的,遍歷算法執行每一個狀態,最終會找到一個最優的可行解。

舉個栗子,今天中午我和同事商量去哪吃飯的問題,我們都不確定去哪一家,于是我就一家一家的數,臊子面,黃燜雞米飯,牛肉拉面,雞湯面......當我說到羊肉泡饃時,我同事眼前一亮,說,走羊肉泡饃走起。。。典型的窮舉法,有么有?


世紀難題,今天中午吃什么?

再如計算100以內的所有奇數,就可以采用枚舉法。


求奇數

那么,適用于窮舉法求解的問題必須滿足哪些條件呢?

(1)、可 預先確定每個解的元素N的個數;

(2)、解元素S1、S2....Sn的可能址為一個連續的值域;

應用窮舉法的場合有: 求不定方程、排列組合、暴力破解算法;

由此可見窮舉法的特點是什么呢?

1、窮舉法的特點:

(1)、可供選擇的答案或元素的范圍是有限的,如今天中午吃什么的問題,我們可供選擇的店就那么多家,并不是無限的;

(2)、可能做了很多無用功、浪費了寶貴的時間,所以導致效率比較低;

(3)、可供選擇的答案或元素是同一類事物,我們選擇去吃飯的地方都是餐館;

(4)、得到的結果肯定是正確的;

(5)、通常會涉及到求極值(如最大,最小,等)。

所以最終得到的結論是:并不是所有的問題都可以使用窮舉法來求解,只有問題的答案個數不是太多時,并且在可以接受的時間內得到結果時才可以使用窮舉法。?

2、窮舉法的優點:?

(1)、算法簡單,比較直觀,易于理解;

(2)、最后一定會得到一個結果。

(3)、從全局觀點使用窮舉法,計算量容易過大,如果在局部地方使用窮舉法,計算的效率會顯著提高。

3、窮舉法的缺點:

(1)、由于窮舉法的特點,將可供選擇的元素逐一的進行篩選,也就造成了程序在運行的時間比較長;

(2)、當可供選擇的答案過大時,可能導致返回結果的時間太長或者其他問題;

4、窮舉法的基本思路:

(1)、確定窮舉對象,窮舉范圍和判定條件;

(2)、逐一枚舉可能的解,驗證是否時問題的解。

5、求解方法和步驟:

(1)、確定可選擇的范圍內的所有解的集合;

(2)、抽象出答案包含的參數,確定每個參數的數據范圍;

(3)、對解的每個參數的數據范圍進行循環遍歷;

(4)、對每次的循環,根據題意給定的范圍判斷是否為解;

(5)、優化程序、以便縮小搜索范圍,提高程序的效率。

6、窮舉法的列舉方式:

(1)順序列舉: 是指答案范圍內的各種情況很容易與自然數對應甚至就是自然數,可以按自然數的變化順序去列舉。

(2)排列列舉: 有時答案的數據形式是一組數的排列,列舉出所有答案所在范圍內的排列,為排列列舉。

(3)組合列舉: 當答案的數據形式為一些元素的組合時,往往需要用組合列舉。組合是無序的。

舉例:百錢百雞問題用窮舉法來求解:

百錢買百雞

這個數學問題的數學方程可列出如下:

Cock+Hen+Chick=100

Cock*5+Hen*3+Chick/3=100

顯然這是個不定方程,適用于窮舉法求解。依次取Cock值域中的一個值,然后求其他兩個數,滿足條件就是解。那么該如何用程序語言來完成呢。

百錢買百雞 代碼塊

最終終端打印的結果為:

打印結果

前面已經提到,由于窮舉法的特點,當問題的可選范圍變大時,循環嵌套的層數越多,計算效率就相對的變低了,此時作為程序員就要對算法做出優化;

如:上面的計算百錢買百雞的代碼中,循環體執行了21*34*101 = 72114次,那么近過分析,從數學的角度來考慮這個問題:根據題意,5x+3y=z/3=100, ? ? x+y+z=100可以消去一個未知數z,最終得到:7x+4y=100, ? x+y+z=100,于是只要枚舉公雞x(最多只有14只),最終就可以求出y和z,可用程序表示:


百錢買百雞 代碼塊

優化后的代碼,只循環了14次,此時的效率明顯提升了,由于電腦的運行速度相當快,其實我并沒有什么明顯的感覺,但是這個問題被無限放大,比如循環次數達到了千萬次時優化就會有很明顯的效果了,那么總結一下如何做出優化:

7、優化策略:

(1)、減少循環次數;

(2)、合理選擇循環的變量;

(3)、注意枚舉的順序;

(4)、減少判斷每種情況的時間。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容