【C++算法基礎(chǔ)】#2暴力枚舉的方法論與優(yōu)化技巧 – 大力出奇跡
暴力枚舉法(Brute Force)是許多剛接觸編程或算法的選手最容易上手,也最明顯的算法。雖然暴力枚舉往往效率極低,但是可以很快地解決一些問(wèn)題。
本文將介紹暴力枚舉法的方法和優(yōu)化技巧。注意本文中許多名字并非專業(yè)學(xué)名,而是我自己定義的,請(qǐng)不要過(guò)于糾結(jié)。

?? 作者:Eriktse
??? 簡(jiǎn)介:19歲,211計(jì)算機(jī)在讀,CCPC全國(guó)賽金牌,ICPC區(qū)域賽銀牌退役選手??力爭(zhēng)以通俗易懂的方式講解編程和算法!??歡迎關(guān)注我,一起交流C++/Python算法。(優(yōu)質(zhì)好文持續(xù)更新中……)??
???歡迎加群一起玩耍~QQ群:600240150
1.確定解的形式(枚舉變量)
在進(jìn)行暴力之前,我們需要分析出解的形式,比如要求滿足條件的三元組的個(gè)數(shù),我們就枚舉所有三元組,檢查哪些滿足條件。比如我們要求滿足條件的區(qū)間的個(gè)數(shù),就可以枚舉所有的二元組(表示左右端點(diǎn))。
有些題目解的形式可能不太唯一,需要選擇合適的形式,對(duì)于不同的形式選擇不同的枚舉方法。比如枚舉子集,可以用循環(huán),也可以用dfs,有時(shí)候在能夠剪枝的情況下,dfs會(huì)比循環(huán)直接枚舉子集快很多。
2.選擇枚舉方法
常見(jiàn)的枚舉方法有直接枚舉法和遞歸枚舉法,根據(jù)題目不同,有時(shí)候也可能有用一些構(gòu)造方法來(lái)進(jìn)行枚舉。
常見(jiàn)的直接枚舉(循環(huán))不會(huì)超過(guò)4層循環(huán),且循環(huán)層數(shù)固定。
如果你發(fā)現(xiàn)循環(huán)層數(shù)是可變的,往往就要用遞歸枚舉,比如你要枚舉所有長(zhǎng)度小于等于的一個(gè)東西,就需要用到遞歸。
3.判斷函數(shù)
在枚舉出一個(gè)解后,我們需要判斷其是否是可行解,于是我們要寫(xiě)一個(gè)判斷函數(shù)。
這個(gè)判斷函數(shù)可以根據(jù)你枚舉出的一個(gè)解,來(lái)判斷這個(gè)解是否可能。
舉個(gè)例子
我們要求范圍的所有質(zhì)數(shù)。
那么我們解的形式就是一個(gè)整數(shù),于是我們遍歷解空間的所有解,說(shuō)人話就是的所有整數(shù),然后編寫(xiě)判斷函數(shù),用于判斷一個(gè)解是否是可行解,即判斷一個(gè)數(shù)字是否是質(zhì)數(shù),并執(zhí)行操作:[YES->將解加入到解集中,NO->舍棄
]。
例題
ETOJ 1014: straax'aks Array
鏈接:http://oj.eriktse.com/problem.php?id=1014
這道題看數(shù)據(jù)范圍,明顯支持,所以可以大膽地暴力,枚舉所有的三元組,并判斷是否滿足條件即可。
代碼:
ETOJ 1016: 全排列
鏈接:http://cdn.oj.eriktse.com/problem.php?id=1016
暴力枚舉,但是我們發(fā)現(xiàn)這次用循環(huán)來(lái)寫(xiě)其實(shí)不好寫(xiě)了,所以改用遞歸。
注意需要按照字典序升序來(lái)寫(xiě)。
代碼: