c++ 遞推演算法

張其勳發表於2023-02-06

各位大佬不妨先點個贊再看文章!


  遞推法是一種重要的數學方法,在數學的各個領域中都有廣泛的運用,也是計算機用於數值計算的一個重要演算法。這種演算法特點是:一個問題的求解需一系列的計算,在已知條件和所求問題之間總存在著某種相互聯絡的關係,在計算時,如果可以找到前後過程之間的數量關係(即遞推式),那麼,從問題出發逐步推到已知條件,此種方法叫逆推。無論順推還是逆推,其關鍵是要找到遞推式。這種處理問題的方法能使複雜運算化為若干步重複的簡單運算,充分發揮出計算機擅長於重複處理的特點。   

  遞推演算法的首要問題是得到相鄰的資料項間的關係(即遞推關係)。遞推演算法避開了求通項公式的麻煩,把一個複雜的問題的求解,分解成了連續的若干步簡單運算。一般說來,可以將遞推演算法看成是一種特殊的迭代演算法。

  如果一道遞推題目你找到了他的遞推關係式,那麼恭喜你,基本是可以拿到80%的分數了。


 

我們先來考慮一個簡單的問題:樓梯有n個臺階,上樓可以一步上一階,也可以一步上兩階。一共有多少種上樓的方法? 這是一道計數問題。在沒有思路時,不妨試著找規律。n=5時,一共有8種方法:5=1+1+1+1+1   5=2+1+1+1 5=1+2+1+1 5=1+1+2+1 5=1+1+1+2 5=2+2+1 5=2+1+2 5=1+2+2  其中有5種方法第1步走了1階(背景灰色),3種方法第1步走了2階,沒有其他可能。假設f(n)為n個臺階的走法總數,把n個臺階的走法分成兩類。

 第1類:第1步走1階,剩下還有n-1階要走,有f(n-1)種方法。

第2類:第1步走2階,剩下還有n-2階要走,有f(n-2)種方法。

這樣,就得到了遞推式:f(n)=f(n-1)+f(n-2),不要忘記邊界情況:f(1)=1,f(2)=2。把f(n)的前幾項列出:1,2,3,5,8,……。


 

   再例如,把雌雄各一的一對新兔子放入養殖場中。每隻雌兔在出生兩個月以後,每月產雌雄各一的一對新兔子。試問第n個月後養殖場中共有多少對兔子。

還是先找找規律。

第1個月:一對新兔子r1。用小寫字母表示新兔子。

第2個月:還是一對新兔子,不過已經長大,具備生育能力了,用大寫字母R1表示。

第3個月:R1生了一對新兔子r2,一共2對。

第4個月:R1又生一對新兔子r3,一共3對。另外,r2長大了,變成R2

第5個月:R1和R2各生一對,記為r4和r5,共5對。此外,r3長成R3。

第6個月:R1、R2和R3各生一對,記為r6~r8,共8對。

此外,r4和r5長大。……

  把這些數排列起來:1,1,2,3,5,8,……,事實上,可以直接推匯出來遞推關係f(n)=f(n-1)+f(n-2):第n個月的兔子由兩部分組成,一部分是上個月就有的老兔子f(n-1),一部分是上個月出生的新兔子f(n-2)(第n-1個月時具有生育能力的兔子數就等於第n-2個月兔子總數)。根據加法原理,f(n)=f(n-1)+f(n-2)。


 


 

下面來看一下五種典型的遞推關係:

 

Ⅰ.Fibonacci數列

在所有的遞推關係中,Fibonacci數列應該是最為大家所熟悉的。在最基礎的程式設計語言Logo語言中,就有很多這類的題目。而在較為複雜的Basic、Pascal、C語言中,Fibonacci數列類的題目因為解法相對容易一些,逐漸退出了競賽的舞臺。可是這不等於說Fibonacci數列沒有研究價值,恰恰相反,一些此類的題目還是能給我們一定的啟發的。 Fibonacci數列的代表問題是由義大利著名數學家Fibonacci於1202年提出的“兔子繁殖問題”(又稱“Fibonacci問題”)。   

問題的提出:有雌雄一對兔子,假定過兩個月便可繁殖雌雄各一的一對小兔子。問過n個月後共有多少對兔子?   

解:設滿x個月共有兔子Fx對,其中當月新生的兔子數目為Nx對。第x-1個月留下的兔子數目設為Fx-1對。則: Fx=Nx+ Fx-1       Nx=Fx-2 (即第x-2個月的所有兔子到第x個月都有繁殖能力了)    

∴ Fx=Fx-1+Fx-2 邊界條件:F0=0,F1=1  

由上面的遞推關係可依次得到     

F2=F1+F0=1,F3=F2+F1=2,F4=F3+F2=3,F5=F4+F3=5,……。  

 Fabonacci數列常出現在比較簡單的組合計數問題中,例如以前的競賽中出現的“骨牌覆蓋”問題。在優選法中,Fibonacci數列的用處也得到了較好的體現


Ⅱ.Hanoi塔問題

問題的提出:Hanoi塔由n個大小不同的圓盤和三根木柱a,b,c組成。開始時,這n個圓盤由大到小依次套在a柱上,如圖3-11所示。 要求把a柱上n個圓盤按下述規則移到c柱上:

 

 

 

 

(1)一次只能移一個圓盤;   

(2)圓盤只能在三個柱上存放;   

(3)在移動過程中,不允許大盤壓小盤。   

問將這n個盤子從a柱移動到c柱上,總計需要移動多少個盤次?

  解:設hn為n個盤子從a柱移到c柱所需移動的盤次。顯然,當n=1時,只需把a 柱上的盤子直接移動到c柱就可以了,故h1=1。當n=2時,先將a柱上面的小盤子移動到b柱上去;然後將大盤子從a柱移到c 柱;最後,將b柱上的小盤子移到c柱上,共記3個盤次,故h2=3。以此類推,當a柱上有n(n2)個盤子時,總是先借助c柱把上面的n-1個盤子移動到b柱上,然後把a柱最下面的盤子移動到c柱上;再借助a柱把b柱上的n-1個盤子移動到c柱上;總共移動hn-1+1+hn-1個盤次。    ∴hn=2hn-1+1

邊界條件:h1=1


 

 

 

Ⅲ.平面分割問題   

  問題的提出:設有n條封閉曲線畫在平面上,而任何兩條封閉曲線恰好相交於兩點,且任何三條封閉曲線不相交於同一點,問這些封閉曲線把平面分割成的區域個數。 解:設an為n條封閉曲線把平面分割成的區域個數。 由圖3-13可以看出:a2-a1=2;a3-a2=4;a4-a3=6。

 

 

 

 

  從這些式子中可以看出an-an-1=2(n-1)。當然,上面的式子只是我們透過觀察4幅圖後得出的結論,它的正確性尚不能保證。下面不妨讓我們來試著證明一下。當平面上已有n-1條曲線將平面分割成an-1個區域後,第n-1條曲線每與曲線相交一次,就會增加一個區域,因為平面上已有了n-1條封閉曲線,且第n條曲線與已有的每一條閉曲線恰好相交於兩點,且不會與任兩條曲線交於同一點,故平面上一共增加2(n-1)個區域,加上已有的an-1個區域,一共有an-1+2(n-1)個區域。所以本題的遞推關係是an=an-1+2(n-1),邊界條件是a1=1。 平面分割問題是競賽中經常觸及到的一類問題,由於其靈活多變,常常感到棘手。

例如下面這題:

  (1998合肥市競賽複試第二題)同一平面內的n(n500)條直線,已知有p(p2)條直線相交於同一點,則這n條直線最多能將平面分割成多少個不同的區域?   

  解:這道題目與第一部分中的平面分割問題十分相似,不同之處就在於線條的曲直以及是否存在共點線條。由於共點直線的特殊性,我們決定先考慮p條相交於一點的直線,然後再考慮剩下的n-p條直線。首先可以直接求出p條相交於一點的直線將平面劃分成的區域數為2p個,然後在平面上已經有k(k>=p)條直線的基礎上,加上一條直線,最多可以與k條直線相交,而每次相交都會增加一個區域,與最後一條直線相交後,由於直線可以無限延伸,還會再增加一個區域。所以fm=fm-1+m (m>p),邊界條件在前面已經計算過了,是fp=2p。

  雖然這題看上去有兩個引數,但是在實際做題中會發現,本題還是屬於帶一個引數的遞推關係。


 

Ⅳ.Catalan數   

   Catalan數首先是由Euler在精確計算對凸n邊形的不同的對角三角形剖分的個數問題時得到的,它經常出現在組合計數問題中。    問題的提出:在一個凸n邊形中,透過不相交於n邊形內部的對角線,把n邊形拆分成若干三角形,不同的拆分數目用hn表示,hn即為Catalan數。例如五邊形有如下五種拆分方案(圖3-14),故h5=5。求對於一個任意的凸n邊形相應的hn。

 

 

 

 

    Catalan數是比較複雜的遞推關係,尤其在競賽的時候,選手很難在較短的時間裡建立起正確的遞推關係。當然,Catalan數類的問題也可以用搜尋的方法來完成,但是,搜尋的方法與利用遞推關係的方法比較起來,不僅效率低,程式設計複雜度也陡然提高


 

 

Ⅴ.第二類Stirling數   

在五類典型的遞推關係中,第二類Stirling是最不為大家所熟悉的。也正因為如此,我們有必要先解釋一下什麼是第二類Strling數。    

【定義2】n個有區別的球放到m個相同的盒子中,要求無一空盒,其不同的方案數用S(n,m)表示,稱為第二類Stirling數。     下面就讓我們根據定義來推導帶兩個引數的遞推關係——第二類Stirling數。 解:設有n個不同的球,分別用b1,b2,……bn表示。從中取出一個球bn,bn的放法有以下兩種:    ①bn獨自佔一個盒子;那麼剩下的球只能放在m-1個盒子中,方案數為S2(n-1,m-1);    ②bn與別的球共佔一個盒子;那麼可以事先將b1,b2,……bn-1這n-1個球放入m個盒子中,然後再將球bn可以放入其中一個盒子中,方案數為mS2(n-1,m)。 綜合以上兩種情況,可以得出第二類Stirling數定理:    

【定理】S2(n,m)=mS2(n-1,m)+S2(n-1,m-1) (n>1,m1) 邊界條件可以由定義2推匯出:     S2(n,0)=0;S2(n,1)=1;S2(n,n)=1;S2(n,k)=0(k>n)。    第二類Stirling數在競賽中較少出現,但在競賽中也有一些題目與其類似,甚至更為複雜。讀者不妨自己來試著建立其中的遞推關係。


 


 

小結:透過上面對五種典型的遞推關係建立過程的探討,可知對待遞推類的題目,要具體情況具體分析,透過找到某狀態與其前面狀態的聯絡,建立相應的遞推關係。

 

 

 

 

相關文章