問題描述:卡塔蘭數,是組合數學
中乙個常出現在各種計數問題中出現的數列。輸入乙個整數n,計算h(n)。其遞迴式如下:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2,h(0) = h(1) = 1)
該遞推關係的解為:h(n)=c(2n,n)/(n+1) (n=1,2,3,...)
思路:直接根據遞迴式,寫出相應的演算法
。參考**:
[cpp]view plain
copy
print?
//函式功能: 計算catalan的第n項
//函式引數: n為項數
//返回值: 第n個catalan數
intcatalan(
intn)
intresult = h[n];
//儲存結果
delete
h;
//注意釋放空間
return
result;
}
應用1描述: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)。
應用2描述:矩陣鏈乘: p=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?
思路:可以這樣考慮,首先通過括號化,將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)。
應用3描述:乙個棧(無窮大)的進棧序列為1,2,3,…,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)。
應用4描述:n個節點構成的二叉樹,共有多少種情形?
思路:可以這樣考慮,根肯定會占用乙個結點,那麼剩餘的n-1個結點可以有如下的分配方式,t(0, n-1),t(1, n-2),...t(n-1, 0),設t(i, j)表示根的左子樹含i個結點,右子樹含j個結點。(t(0, n-1)=f(0)*f(n-1),因為是分步驟,當然要相乘)
設問題的解為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)。
拓展:n個非葉節點的滿二叉樹的形態數(對稱後得到的二叉樹除非自己本身對稱,否則算是不同),這裡取wikipedia上的一張說明問題:
這裡要求滿二叉樹,實際上就是在上一點的每個子節點的空兒子上都加上葉子,就形成了我們的圖了,那麼我們要求的結果就是就是n個節點構成的二叉樹的情形數。
應用5描述:在圓上選擇2n個點,將這些點成對連線起來使得所得到的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)。
應用6描述:求乙個凸多邊形區域劃分成三角形區域的方法數?
1.我們從最簡單情況開始:n=3,f(3)=1;
2.當n=4,f(4)=2;
3.n邊時
我們從節點1開始考慮,要想分割成三角形區域,1不能和與它相鄰的點連線,所以1可以連線3,4,...,n-1;
假設1連線i,則分割成的兩個區域分別為i凸多邊形和n+2-i凸多邊形,即對於節點1,f(n)=f(3)f(n+2-3)+f(4)f(n+2-4)+...+f(n-1)f(3);
設f(2) = 1,那麼f(3) = 1, f(4) = 2, f(5) = 5。結合遞推式,不難發現f(n) 等於h(n-2)。
應用7描述:有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?
思路:可以將持5元買票視為進棧,那麼持10元買票視為5元的出棧。這個問題就轉化成了棧的出棧次序數。由應用三的分析直接得到結果,f(2n) 等於h(n)。
**:
卡特蘭數,高精度卡特蘭數
簡單介紹 卡特蘭數是組合數學中常常出現的乙個數列。個人認為不管是遞推公式還是代表的含義都比斐波那契數列難理解一些。遞推公式 應用 1.cn表示長度2n的dyck word的個數。dyck word是乙個有n個x和n個y組成的字串。且全部的字首字串皆滿足x的個數大於等於y的個數。下面為長度為6的dyc...
卡特蘭數和超級卡特蘭數
這篇部落格主要是想講一下超級卡特蘭數 大施洛德數 順帶就想講一下卡特蘭數.卡特蘭數記為 c n c 1 1 forall n geq 2,c n sum c i c 前幾項大概是 1,1,2,5,14,42,132.直接遞推未免效率太低,我們考慮用生成函式優化.顯然有 c x c x 2 x 解得 ...
卡特蘭數 Catalan
問題 程式設計之美 第4.3節中提到了 買票找零 問題,查閱了下資料,此問題和卡特蘭數 cn有關,其定義如下 卡特蘭數真是乙個神奇的數字,很多組合問題的數量都和它有關係,例如 yyy xyxxyy xyxyxy xxyyxy xxyxyy ab c d a bc d ab cd a bc d a b...