卡特蘭數(catalan)

卡特蘭數

卡特蘭數是組合數學中一個常出現在各種計數問題中出現的數列。

卡特蘭數前幾項爲 : C0=1,C1=1,C2=2,C3=5,C4=14,C5=42,C6=132,C7=429,C8=1430,C9=4862,C10=16796

1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, 18367353072152, 69533550916004, 263747951750360, 1002242216651368, 3814986502092304, 14544636039226909, 55534064877048198, 212336130412243110, 812944042149730764, 3116285494907301262, 11959798385860453492, 45950804324621742364, ...

輸入一個整數n,計算h(n)。

令h(0)=1,h(1)=1,Catalan數滿足遞推式:h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)*h(0) (n>=2)
例如:

h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
另類遞推式:h(n)=h(n-1)*(4*n-2)/(n+1);
遞推關係的解爲:h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
遞推關係的另類解爲:h(n)=C(2n,n)-C(2n,n+1)(n=0,1,2,...)

直接根據遞歸式,寫出相應的算法:

  1. //函數功能: 計算Catalan的第n項  
  2. //函數參數: n爲項數  
  3. //返回值:   第n個Catalan數  
  4. int Catalan(int n)  
  5. {  
  6.     if(n <= 1)  
  7.         return 1;  
  8.   
  9.     int *h = new int [n+1]; //保存臨時結果  
  10.     h[0] = h[1] = 1;        //h(0)和h(1)  
  11.     for(int i = 2; i <= n; i++)    //依次計算h(2),h(3)...h(n)  
  12.     {  
  13.         h[i] = 0;  
  14.         for(int j = 0; j < i; j++) //根據遞歸式計算 h(i)= h(0)*h(i-1)+h(1)*h(i-2) + ... + h(i-1)h(0)  
  15.             h[i] += (h[j] * h[i-1-j]);  
  16.     }  
  17.     int result = h[n]; //保存結果  
  18.     delete [] h;       //注意釋放空間  
  19.     return result;  
  20. }  

卡特蘭數的應用

應用1:出棧次序。一個棧(無窮大)的進棧序列爲1,2,3,…,n,有多少個不同的出棧序列?h(n)
常規分析

首先,我們設f(n)=序列個數爲n的出棧序列種數。同時,我們假定,從開始到棧第一次出到空爲止,這段過程中第一個出棧的序數是k。特別地,如果棧直到 整個過程結束時才空,則k=n。首次出空之前第一個出棧的序數k將1~n的序列分成兩個序列,其中一個是1~k-1,序列個數爲k-1,另外一個是 k+1~n,序列個數是n-k。此時,我們若把k視爲確定一個序數,那麼根據乘法原理,f(n)的問題就等價於——序列個數爲k-1的出棧序列種數乘以序 列個數爲n - k的出棧序列種數,即選擇k這個序數的f(n)=f(k-1)×f(n-k)。而k可以選1到n,所以再根據加法原理,將k取不同值的序列種數相加,得到 的總序列種數爲:f(n)=f(0)f(n-1)+f(1)f(n-2)+……+f(n-1)f(0)。看到此處,再看看卡特蘭數的遞推式,答案不言而 喻,即爲f(n)=h(n)= C(2n,n)/(n+1)= c(2n,n)-c(2n,n+1)(n=0,1,2,……)。最後,令f(0)=1,f(1)=1。
非常規分析
對於每一個數來說,必須進棧一次、出棧一次。我們把進棧設爲狀態‘1’,出棧設爲狀態‘0’。n個數的所有狀態對應n個1和n個0組成的2n位二進制數。 由於等待入棧的操作數按照1‥n的順序排列、入棧的操作數b大於等於出棧的操作數a(a≤b),因此輸出序列的總數目=由左而右掃描由n個1和n個0組成 的2n位二進制數,1的累計數不小於0的累計數的方案種數。在2n位二進制數中填入n個1的方案數爲c(2n,n),不填1的其餘n位自動填0。從中減去 不符合要求(由左而右掃描,0的累計數大於1的累計數)的方案數即爲所求。
不符合要求的數的特徵是由左而右掃描時,必然在某一奇數位2m+1位上首先出現m+1個0的累計數和m個1的累計數,此後的2(n-m)-1位上有n-m 個 1和n-m-1個0。如若把後面這2(n-m)-1位上的0和1互換,使之成爲n-m個0和n-m-1個1,結果得1個由n+1個0和n-1個1組成的 2n位數,即一個不合要求的數對應於一個由n+1個0和n-1個1組成的排列。反過來,任何一個由n+1個0和n-1個1組成的2n位二進制數,由於0的 個數多2個,2n爲偶數,故必在某一個奇數位上出現0的累計數超過1的累計數。同樣在後面部分0和1互換,使之成爲由n個0和n個1組成的2n位數,即 n+1個0和n-1個1組成的2n位數必對應一個不符合要求的數。因而不合要求的2n位數與n+1個0,n-1個1組成的排列一一對應。
顯然,不符合要求的方案數爲c(2n,n+1)。由此得出輸出序列的總數目=c(2n,n)-c(2n,n+1)=c(2n,n)/(n+1)=h(n)。

應用2描述:n對括號有多少種匹配方式?h(n)
       思路:
n對括號相當於有2n個符號,n個左括號、n個右括號,可以設問題的解爲f(2n)。第0個符號肯定爲左括號,與之匹配的右括號必須爲第2i+1 字符。因爲如果是第2i個字符,那麼第0個字符與第2i個字符間包含奇數個字符,而奇數個字符是無法構成匹配的。
       通過簡單分析,f(2n)可以轉化如下的遞推式 f(2n) = f(0)*f(2n-2) + f(2)*f(2n - 4) + ... + f(2n - 4)*f(2) + f(2n-2)*f(0)。簡單解釋一下,f(0) * f(2n-2)表示第0個字符與第1個字符匹配,同時剩餘字符分成兩個部分,一部分爲0個字符,另一部分爲2n-2個字符,然後對這兩部分求解。 f(2)*f(2n-4)表示第0個字符與第3個字符匹配,同時剩餘字符分成兩個部分,一部分爲2個字符,另一部分爲2n-4個字符。依次類推。
       假設f(0) = 1,計算一下開始幾項,f(2) = 1, f(4) = 2, f(6) = 5。結合遞歸式,不難發現f(2n) 等於h(n)。
應用3描述:矩陣鏈乘: P=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?h(n-1)
       思路:
可以這樣考慮,首先通過括號化,將P分成兩個部分,然後分別對兩個部分進行括號化。比如分成(a1)×(a2×a3.....×an),然後再對 (a1)和(a2×a3.....×an)分別括號化;又如分成(a1×a2)×(a3.....×an),然後再對(a1×a2)和 (a3.....×an)括號化。
       設n個矩陣的括號化方案的種數爲f(n),那麼問題的解爲
        f(n) = f(1)*f(n-1) + f(2)*f(n-2) + f(3)*f(n-3) + f(n-1)*f(1)。f(1)*f(n-1)表示分成(a1)×(a2×a3.....×an)兩部分,然後分別括號化。
       計算開始幾項,f(1) = 1, f(2) = 1, f(3) = 2, f(4) = 5。結合遞歸式,不難發現f(n)等於h(n-1)。
應用4描述(和應用1一樣):一個棧(無窮大)的進棧序列爲1,2,3,…,n,有多少個不同的出棧序列?h(n)
       思路:
這個與加括號的很相似,進棧操作相當於是左括號,而出棧操作相當於右括號。n個數的進棧次序和出棧次序構成了一個含2n個數字的序列。第0個數字 肯定是進棧的數,這個數相應的出棧的數一定是第2i+1個數。因爲如果是2i,那麼中間包含了奇數個數,這奇數個肯定無法構成進棧出棧序列。
       設問題的解爲f(2n), 那麼f(2n) = f(0)*f(2n-2) + f(2)*f(2n-4) + f(2n-2)*f(0)。f(0) * f(2n-2)表示第0個數字進棧後立即出棧,此時這個數字的進棧與出棧間包含的數字個數爲0,剩餘爲2n-2個數。f(2)*f(2n-4)表示第0個 數字進棧與出棧間包含了2個數字,相當於1 2 2 1,剩餘爲2n-4個數字。依次類推。
       假設f(0) = 1,計算一下開始幾項,f(2) = 1, f(4) = 2, f(6) = 5。結合遞歸式,不難發現f(2n) 等於h(n)。
應用5描述:n個節點構成的二叉樹,共有多少種情形?h(n)
       思路:
可以這樣考慮,根肯定會佔用一個結點,那麼剩餘的n-1個結點可以有如下的分配方式,T(0, n-1),T(1, n-2),...T(n-1, 0),設T(i, j)表示根的左子樹含i個結點,右子樹含j個結點。
       設問題的解爲f(n),那麼f(n) = f(0)*f(n-1) + f(1)*f(n-2) + .......+ f(n-2)*f(1) + f(n-1)*f(0)。假設f(0) = 1,那麼f(1) = 1, f(2) = 2, f(3) = 5。結合遞推式,不難發現f(n)等於h(n)。
應用6描述:在圓上選擇2n個點,將這些點成對連接起來使得所得到的n條線段不相交的方法數?h(n)
       思路:以其中一個點爲基點,編號爲0,然後按順時針方向將其他點依次編號。那麼與編號爲0相連點的編號一定是奇數,否則,這兩個編號間含有奇數個點,勢 必會有個點被孤立,即在一條線段的兩側分別有一個孤立點,從而導致兩線段相交。設選中的基點爲A,與它連接的點爲B,那麼A和B將所有點分成兩個部分,一 部分位於A、B的左邊,另一部分位於A、B的右邊。然後分別對這兩部分求解即可。
       設問題的解f(n),那麼f(n) = f(0)*f(n-2) + f(2)*f(n-4) + f(4)*f(n-6) + ......f(n-4)*f(2) + f(n-2)*f(0)。f(0)*f(n-2)表示編號0的點與編號1的點相連,此時位於它們右邊的點的個數爲0,而位於它們左邊的點爲2n-2。依次 類推。
       f(0) = 1, f(2) = 1, f(4) = 2。結合遞歸式,不難發現f(2n) 等於h(n)。
應用7描述:求一個凸多邊形區域劃分成三角形區域的方法數?h(n-2)
      思路:以凸多邊形的一邊爲基,設這條邊的2個頂點爲A和B。從剩餘頂點中選1個,可以將凸多邊形分成三個部分,中間是一個三角形,左右兩邊分別是兩個凸多邊形,然後求解左右兩個凸多邊形。
      設問題的解f(n),其中n表示頂點數,那麼f(n) = f(2)*f(n-1) + f(3)*f(n-2) + ......f(n-2)*f(3) + f(n-1)*f(2)。f(2)*f(n-1)表示三個相鄰的頂點構成一個三角形,那麼另外兩個部分的頂點數分別爲2和n-1。
      設f(2) = 1,那麼f(3) = 1, f(4) = 2, f(5) = 5。結合遞推式,不難發現f(n) 等於h(n-2)。
應用8描述:有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?h(n)
     思路:可以將持5元買票視爲進棧,那麼持10元買票視爲5元的出棧。這個問題就轉化成了棧的出棧次序數。由應用2的分析直接得到結果,f(2n) 等於h(n)。

PS應用8:遊樂園門票1元一張,每人限購一張。現在有10個小朋友排隊購票,其中5個小朋友每人只有1元的鈔票一張,另5個小朋友每人只有2元的鈔票一張,售票員沒有準備零錢。問:有多少種排隊方法,使售票員總能找的開零錢?

答:現把拿1元的5個小朋友看成是相同的,把拿2元的5個小朋友也看成是相同的,使用我們常用的“逐點累加法”:

圖 中每條小橫段表示拿1元的小朋友,每條小豎段表示拿2元的小朋友,要求從A走到B的過程中網格中任何點均有橫段數不小於豎段數:拿1元的要先,且人數不能 少於拿2元的,即不能越過對角線AB:每個點所標的數即爲從A走到此點的方法數。求從A到B的走法的方法數。逐點累加可求出爲42,即卡特蘭數C5=42。


又由於每個小朋友是不相同的,所以共有42×5!×5!=42×120×120=604800種情況。

若把此題的10個人,拿1元的有5人,拿2元的有5人改爲共有2n個人,拿1元的n人,拿2元的n人,則符合要求的排隊方法數爲:n!*n!*h(n)=n!*n!*C(2n,n)/(n+1)=(2n)!/(n+1)

卡特蘭數的實例:

組合數學中有非常多的組合結構可以用卡塔蘭數來計數。在Richard P. Stanley的Enumerative Combinatorics: Volume 2一書的習題中包括了66個相異的可由卡塔蘭數表達的組合結構。以下用Cn=3和Cn=4舉若干例:
例1.Cn表示長度2n的dyck word的個數。Dyck word是一個有n個X和n個Y組成的字串,且所有的前綴字串皆滿足X的個數大於等於Y的個數。以下爲長度爲6的dyck words:  h(3)=5
XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY
例2.將上例的X換成左括號,Y換成右括號,Cn表示所有包含n組括號的合法運算式的個數:h(3)=5
((())) ()(()) ()()() (())() (()())
例3.Cn表示有n個節點組成不同構二叉樹的方案數。下圖中n等於3,圓形表示節點,月牙形表示什麼都沒有。h(3)=5


例4.Cn表示所有在n × n格點中不越過對角線的單調路徑的個數。一個單調路徑從格點左下角出發,在格點右上角結束,每一步均爲向上或向右。計算這種路徑的個數等價於計算Dyck word的個數: X代表“向右”,Y代表“向上”。下圖爲n = 4的情況:h(4)=14

類似:一位大城市的律師在她住所以北n個街區和以東n個街區處工作。每天她走2n個街區去上班。如果她從不穿越(但可以碰到)從家到辦公室的對角線,那麼有多少條可能的道路?h(n)



例5.Cn表示通過連結頂點而將n邊的凸多邊形分成三角形的方法個數。下圖中爲n=6的情況:h(n-2)=h(4)=14


例6.Cn表示用n個長方形填充一個高度爲n的階梯狀圖形的方法個數。下圖爲 n = 4的情況:h(4)=14


例7.進棧出棧問題:
飯後,姐姐洗碗,妹妹把姐姐洗過的碗一個一個放進碗櫥摞成一摞。一共有n個不同的碗,洗前也是摞成一摞的,也許因爲小妹貪玩而使碗拿進碗櫥不及時,姐姐則把洗過的碗摞在旁邊,問:小妹摞起的碗有多少種可能的方式?h(n)
一個汽車隊在狹窄的路面上行駛,不得超車,但可以進入一個死衚衕去加油,然後再插隊行駛,共有n輛汽車,問共有多少種不同的方式使得車隊開出城去?h(n)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章