演算法基礎(一) 列舉

2021-08-18 19:33:55 字數 2510 閱讀 4952

慕課:程式設計與演算法(二)演算法基礎 郭瑋老師課程的學習筆記

列舉,基於逐個嘗試答案的一種文體求解策略,根據所有可能的情況,並且一一判斷。

大家可能會說列舉不就是一種簡單的將資料全都遍歷一遍嗎,但是在這裡我們將列舉進行優化,讓列舉更加聰明,從而達到演算法的目的,即提供更快更好的解題的方法,這樣列舉就不是一種簡單的遍歷,而是一種高大上的演算法方法。

列舉也並不是每一種可能都需要嘗試,可以根據題目的要求按照從小到大的遍歷順序、或者對列舉的範圍進行限定,從而減小列舉的次數、時間等,從而進行優化演算法。

同時,題目有時沒有給出明確的列舉條件,我們需要從題目中找出需要列舉的量及列舉的範圍。

1、例題:完美立方

對於這一題,簡單的求解就是可以對a<=100,b<=100,c<=100,d<=100進行四層迴圈巢狀,a在最外面,d在最裡層,如果結果滿足且b<=c<=d則輸出。但是我們會發現對於那種b<=c<=d的情況完全可以不進行計算,而直接排除,減少計算的次數,如圖

這裡我們直接對迴圈遍歷的範圍進行限定,a的列舉範圍為[2,n],b的列舉範圍為[2,a-1],c的列舉範圍為[b,a-1],d的列舉範圍為[c,a-1],b、c、d直接限定最大值小於a,並且c、d開始的最小值限定在b和c,可以自動滿足b<=c<=d這個條件,但是從次數上可以減少很多,從而優化計算。

2、生理週期

簡單的嘗試思路,就是可以對d+1開始直到21252天,每天嘗試是否是23、28、33的倍數,但是這樣嘗試需要遍歷20000多次,如圖,我們該怎麼提高列舉效率

我們知道三天同時出現高峰期時必須是體力的高峰期,所以我們首先找體力的高峰期,即每23天乙個迴圈,再找體力高峰期出現的日子裡是不是情商的高峰期,即是不是每28天乙個迴圈,差為28的倍數,如果是則證明即時體力的高峰期又是情商的高峰期,接下來就判斷是不是智商的高峰期,即差是不是33的倍數;否則,加23,移到下乙個體力的高峰期,直到找到乙個體力和情商的雙高峰期,然後判斷智商的高峰期。智商同理,如果不是智商的高峰期,則需要移到下乙個體力和情商的高峰期,加23*28;否則輸出,即三個的高峰期。

優化演算法,只有在體力高峰期的時候才需要判斷是不是情商的高峰期,即每隔23天判斷情商高峰期,如果是情商高峰期,則判斷智商高峰期,如果不是智商高峰期,則每隔23*28即體力和情商雙高峰期時才判斷體力高峰期。

3、稱硬幣

給出稱的結果前提下找真假幣,並判斷假幣輕還是重,不是計算演算法稱真假幣

這道題我們可以列舉從a開始逐個假設是假幣並假設輕、重,即如下圖,對於a-l,分別假設輕、重併呼叫函式進行判斷此時這種情況是否成立

如果假幣輕,則應該出現在高的那一邊,重,則出現在低的那一邊,且天平平衡時肯定沒有出現假幣,每次列舉時都進行判斷,如果結果正確則說明假設正確,這枚幣為假幣並且輕重也是假設正確

3、熄燈問題

輸出的是開關按動的方案,並且注意乙個開關按一次是開,按兩次就是關相當於沒按,所以開關值為0和1,不存在其他次數

而且開關次序也沒關係,先按哪個再按哪個結果是一樣的

乙個簡單的想法就是列舉所有開關的可能取值,即每個開關兩個值0和1,狀態數即2的30次方,超時,需要一種優化的方案

不對全部開關進行列舉,而是選擇一部分,例如第一行的狀態2的6次方確定後,想要改變第一行的狀態只能改變第二行,第二行也就確定了,以此類推,那麼後面也就確定,所以只需要遍歷第一行的燈

優化演算法:

輸入儲存:只需要乙個一維的char型別資料,乙個char為8位,一行只需要6位即可,一行6個位元,即5行5個char,使用位運算來進行

用二進位制數進行列舉:對於第一行的列舉可以優化為,對於2的次方的列舉,可以用int來累加從0開始到2的k次方減1,即k位01的組合,即2的k次方減1種,例如00,01,10,11->0,1,2,3,用二進位制數進行列舉

演算法基礎(1) 列舉

列舉在大家看來可能是乙個非常簡單的問題,不就是乙個遍歷演算法嘛,有什麼好說的,然而,在參加了北京大學mooc的演算法基礎後,我直接被震驚了。原來列舉演算法還能這麼玩!好吧,不說有的沒得沒得了,先來看第乙個例子 熄燈問題 這個問題的描述如下 乙個由按鈕組成的矩陣,其中每行有6個按鈕,共5行。每個按鈕的...

C C 高階學習筆記(一) 列舉型別

為了在c c 的學習之路中留下更深刻的印象,從現在開始,我將著手寫一系列的c c 高階學習筆記,文章中不涉及深層次的應用,不作教科書式的詳解,只寫出基本的用法和介紹,以後在學習和工作過程中有用到的功能再作補充,保證介紹的簡潔 實用和高效 歡迎到 我的部落格 檢視更詳細的內容 有時候在開發中需要定義一...

VC 串列埠筆記 一 列舉電腦串列埠

vc 串列埠筆記 一 列舉電腦串列埠 2012年01月14日 1.從登錄檔讀取資訊 如下 從登錄檔讀取串列埠 1 void ccommdlg enumcommport clistbox plistbox 2 16 if memcmp regkeyname,device 8 過濾虛擬串列埠 17 20...