問題描述:卡塔蘭數,是組合數學中一個常出如今各類計數問題中出現的數列。輸入一個整數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,...)算法
思路:直接根據遞歸式,寫出相應的算法。函數
參考代碼:this
//函數功能: 計算Catalan的第n項 //函數參數: n爲項數 //返回值: 第n個Catalan數 int Catalan(int n) { if(n <= 1) return 1; int *h = new int [n+1]; //保存臨時結果 h[0] = h[1] = 1; //h(0)和h(1) for(int i = 2; i <= n; i++) //依次計算h(2),h(3)...h(n) { h[i] = 0; for(int j = 0; j < i; j++) //根據遞歸式計算 h(i)= h(0)*h(i-1)+h(1)*h(i-2) + ... + h(i-1)h(0) h[i] += (h[j] * h[i-1-j]); } int result = h[n]; //保存結果 delete [] h; //注意釋放空間 return result; }
應用1描述:n對括號有多少種匹配方式?spa
思路:n對括號至關於有2n個符號,n個左括號、n個右括號,能夠設問題的解爲f(2n)。第0個符號確定爲左括號,與之匹配的右括號必須爲第2i+1字符。由於若是是第2i個字符,那麼第0個字符與第2i個字符間包含奇數個字符,而奇數個字符是沒法構成匹配的。.net
經過簡單分析,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個字符。依次類推。code
假設f(0) = 1,計算一下開始幾項,f(2) = 1, f(4) = 2, f(6) = 5。結合遞歸式,不難發現f(2n) 等於h(n)。blog
應用2描述:矩陣鏈乘: P=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?遞歸
思路:能夠這樣考慮,首先經過括號化,將P分紅兩個部分,而後分別對兩個部分進行括號化。好比分紅(a1)×(a2×a3.....×an),而後再對(a1)和(a2×a3.....×an)分別括號化;又如分紅(a1×a2)×(a3.....×an),而後再對(a1×a2)和(a3.....×an)括號化。ip
設n個矩陣的括號化方案的種數爲f(n),那麼問題的解爲get
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個結點。
設問題的解爲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)。
應用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描述:求一個凸多邊形區域劃分紅三角形區域的方法數?
思路:以凸多邊形的一邊爲基,設這條邊的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)。
應用7描述:有2n我的排成一行進入劇場。入場費5元。其中只有n我的有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?
思路:能夠將持5元買票視爲進棧,那麼持10元買票視爲5元的出棧。這個問題就轉化成了棧的出棧次序數。由應用三的分析直接獲得結果,f(2n) 等於h(n)。
本人享有博客文章的版權,轉載請標明出處 http://blog.csdn.net/wuzhekai1985