常用演算法-窮舉法

來源:互聯網
上載者:User

標籤:sdn   思想   details   blog   枚舉法   嚴格   net   代碼   article   

窮舉法又稱為枚舉法,它是在電腦演算法設計中用得最多的一種編程思想。它的實現方式是:在已知答案範圍的情況下,依次地枚舉該範圍內所有的取值,並對每個取值進行考查,確定是否滿足條件。經過迴圈遍曆之後,篩選出符合要求的結果來。這種方法充分利用了電腦運算速度快的特點,思路簡單直接,能夠解決大部分的問題。

什麼樣的問題適合使用窮舉法來解決呢?歸納起來,遇到了如下的三種情況,將優先考慮使用窮舉法:

1. 答案的範圍已知:

雖然事先並不知道確切的結果,但能預計到結果會落在哪個取值範圍內。譬如說:

①求1-100之間所有的素數: 無論結果如何,都在1-100的範圍之內。

②求2000-2015年間有幾個月的13號是周日?這15年間共有180個月,月份的個數最多不會超過180

③驗證1000以內的哥德巴哈猜想:即找出1000之內所有的合數,看是否能夠分解為兩個質數之和

。。。。。。

如果仔細觀察,將會發現許多題目的結果範圍都是已知的,都可以使用窮舉法來實現。

2. 答案的結果是離散的,不是連續的。如果要求出1-2之間所有的小數,就無法用窮舉法來實現,因為其結果是無限連續的。

3. 對時間上的要求不嚴格。藍橋杯比賽中的許多題目對於演算法的設計是有時間要求的,有時會非常苛刻。如果用窮舉法則耗時過長,不可取。例如求出21位的水仙花數,使用窮舉法可能會花費30分鐘的時間。而藍橋杯試題通常要求時間限制在1秒鐘之內完成,少數會延長至3分鐘。在這種情況下,必須使用新的演算法來解決問題。

下面舉個經典的例子:

100塊磚100人來搬,男人一人搬4塊,女人一人搬3塊,小孩3人抬一塊,問男,女,小孩各幾人?

若設男,女,小孩人數分別為X, Y, Z,則只能夠列出兩個等式: X+Y+Z=100  4*X+3*Y+Z/3=100 。三個未知數兩個等式,無法求解。這就只能夠使用窮舉法來實現,具體做法如下:

先確定每種類型人員的數量的取值範圍,由題意可知,男人X的取值範圍是0~100/4=25 女人Y的取值範圍是0~100/3=33 小孩的取值範圍是0~99(必須不大於100且為3的倍數)。使用窮舉法遍曆所有可能的取值結果,逐一判斷篩選出正確的結果。編程如下:

for(int x=0; x<=25; x++)

for(int y=0; y<=33; y++)

  for(int z=0; z<=99; z+=3)

    if((x+y+z==100)&&(4*x+3*y+z/3==100)) 

{輸出找到的結果}

如果仔細分析一下,就會發現由於x+y+z==100,那麼只需要考慮x和y的遍曆取值;z值可以通過100-x - y來實現。當然,z值是3的倍數,上述代碼可修改如下:

for(int x=0; x<=25; x++)

for(int y=0; y<=33; y++)

  {    

int z = 100 - x - y;

if((z%3==0)&&(4*x+3*y+z/3==100)) 

{輸出找到的結果}

}

 

從這道題的解決過程中,我們可以發現使用窮舉法的一般過程:

確定需要哪幾個變數,此題需要3個變數x,y, z  如果是其它的題目,所需變數的個數與類型有可能不盡相同,這個要由具體情況而定。

確定每個變數的取值範圍,如上例之中X的範圍是0~25, y的取值範圍是0~33, z的取值範圍是0~33

設定多層的嵌套迴圈,通常為for迴圈,最內層之中設定條件判斷,滿足輸出條件時,輸出相關的提示資訊。

再來一道可以使用窮舉法解決的問題:

有一群海盜(不多於20人),在船上比拼酒量。過程如下:開啟一瓶酒,所有在場的人平分喝下,有幾個人倒下了。再開啟一瓶酒平分,又有倒下的,再次重複...... 直到開了第4瓶酒,坐著的已經所剩無幾,海盜船長也在其中。當第4瓶酒平分喝下後,大家都倒下了。 等船長醒來,發現海盜船擱淺了。他在航海日誌中寫到:“......昨天,我正好喝了一瓶.......奉勸大家,開船不喝酒,喝酒別開船......”

 請你根據這些資訊,推斷開始有多少人,每一輪喝下來還剩多少人。 如果有多個可能的答案,請列出所有答案,每個答案佔一行。格式是:人數,人數,...

 例如,有一種可能是:20,5,4,2,0

藍橋杯中的許多題目都會提供一個答案的樣本,通過分析這個樣本可以加深對當前這道題的理解。以本題為例,通過研究樣本答案可以看出如下的特點:

(1)答案只可能有4個數,分別代表每輪參與的人數,最後的0是固定的。

(2)每輪的人數是不斷減少的,下一輪只能夠比上一輪人數更少。

(3)每輪人數被1除之後,累加和是1(剛好一瓶酒)

即 1/20+1/5+1/4+1/2=1

根據上述的分析,可以確定如下的變數s1, s2, s3, s4分別代表每輪的人數。

這四個變數的取值範圍分別是 1≤s1≤20   1≤s2≤s1   1≤s3≤s2       1≤s4≤s3  據此來設定4層的嵌套迴圈,並加上最內層的條件判斷如下:

for(int s1=1; s1<=20; s1++)

for(int s1=1; s1<=20; s1++)

for(int s1=1; s1<=20; s1++)

for(int s1=1; s1<=20; s1++)

if(1/s1+1/s2+1/s3+1/s4==1){輸出結果} 

理論上來看是正確的,但實際運行時,由於/運算子在左右兩邊均為整數時,表示整除而不是除法,所以上述的條件判斷需要改寫為更複雜的形式:

(s1*s2*s3+s1*s3*s4+s1*s3*s4+s2*s3*s4)/(s1*s2*s3*s4)==1

 

  根據筆者指導藍橋杯的經驗,至少有三分之一的問題都可以通過窮舉的方法來實現,因此,把窮舉法練習使用好,意義非常重大。

 

作業:

 (1) 換分幣: 將5元的人民幣兌換成1元,5角和1角的硬幣,共有多少種不同的兌換方法?

   (2) 找完數: 求1~100內完數的個數。 如果一個數等於它的因子之和,則稱該數為完數(或“完全數”)。例如,6的因子為1,2, 3 而6=1+2+3 , 因此6是完數

(3)找自守數:自守數是指一個數的平方的尾數等於該數自身的自然數。例如:5*5=25; 25*25=625; 76*76=5776; 9376*9376=87909376, 求100000以內的自守數。

 

連結:49516935

常用演算法-窮舉法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.