卡特蘭數

Codeblock的快捷鍵說明:

1、按住Ctrl滾滾輪,代碼的字體會隨你心意變大變小

2 在編輯區按住右鍵可拖動代碼

3Ctrl+D可複製當前行或選中塊

4Ctrl+Shift+C註釋掉當前行或選中塊,Ctrl+Shift+X則解除註釋。

5Tab縮進當前行或選中塊,Shift+Tab減少縮進

6、需要更大編輯空間時,F2Shift+F2分別可以顯隱下方Logs & others欄和左方的Management

7Ctrl+PageUp 到達上一個函數,Ctrl+PageDown 到達下一個函數。 • Ctrl+B 添加書籤

 

 

void *memset(void *s,int ch,size_t n);

函數解釋:將 s 中前 n 個字節用 ch 替換並返回 s

頭文件:#include


 

//卡特蘭數:

h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

 

h(n)=C(2n,n)/(n+1) (n=0,1,2,...)

 

h(n ) = h(n-1)*(4*n-2) / (n+1)

 

 

卡特蘭數:規定h(0)1,而h(1)1h(2)2h(3)5h(4)14h(5)42h(6)132h(7)429h(8)1430h(9)4862h(10)16796h(11)58786h(12)208012h(13)742900h(14)2674440h(15)9694845···

 

1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, …

 

應用:

1、括號化

矩陣鏈乘: P=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?(h(n-1))

f(n) = f(1)*f(n-1) + f(2)*f(n-2) + f(3)*f(n-3) + f(n-1)*f(1)

h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

f(n) = h(n-1)   n>=3(因爲hn)中,n>=2 )

2、出棧次序

一個棧(無窮大)的進棧序列爲123,…,n,有多少個不同的出棧序列?

分析:對於每一個數來說,必須進棧一次、出棧一次。我們把進棧設爲狀態‘1’,出棧設爲狀態‘0’。n個數的所有狀態對應n1n0組成的2n位二進制數。由於等待入棧的操作數按照1n的順序排列、入棧的操作數b大於等於出棧的操作數a(ab),因此輸出序列的總數目=由左而右掃描由n1n0組成的2n位二進制數,1的累計數不小於0的累計數的方案種數。

    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(2n) = h(n)

 

類似問題:

n對括號有多少種匹配方式?( hn) )

3、凸多邊形三角劃分

在一個凸多邊形中,通過若干條互不相交的對角線,把這個多邊形劃分成了若干個三角形。現在的任務是鍵盤上輸入凸多邊形的邊數n,求不同劃分的方案數fn)。比如當n=6時,f6=14

分析:因爲凸多邊形的任意一條邊必定屬於某一個三角形,所以我們以某一條邊爲基準,以這條邊的兩個頂點爲起點P1和終點PnPPoint),將該凸多邊形的頂點依序標記爲P1P2、……、Pn,再在該凸多邊形中找任意一個不屬於這兩個點的頂點Pk2<=k<=n-1),來構成一個三角形,用這個三角形把一個凸多邊形劃分成兩個凸多邊形,其中一個凸多邊形,是由P1P2,……,Pk構成的凸k邊形(頂點數即是邊數),另一個凸多邊形,是由PkPk+1,……,Pn構成的凸n-k+1邊形。

此時,我們若把Pk視爲確定一點,那麼根據乘法原理,fn)的問題就等價於——凸k多邊形的劃分方案數乘以凸n-k+1多邊形的劃分方案數,即選擇Pk這個頂點的fn=fk)×fn-k+1)。而k可以選2n-1,所以再根據加法原理,將k取不同值的劃分方案相加,得到的總方案數爲:

fn=f2fn-2+1+f3fn-3+1+……+fn-1f2)。

fn=hn-2) (n=234,……)。

最後,令f2=1f3=1

 

思路:以凸多邊形的一邊爲基,設這條邊的2個頂點爲AB。從剩餘頂點中選1個,可以將凸多邊形分成三個部分,中間是一個三角形,左右兩邊分別是兩個凸多邊形,然後求解左右兩個凸多邊形。

設問題的解f(n),其中n表示頂點數,設f(2) = 1,那麼f(3) = 1, f(4) = 2, f(5) = 5f(2)*f(n-1)表示三個相鄰的頂點構成一個三角形,那麼另外兩個部分的頂點數分別爲2n-1。那麼

f(n) = f(2)*f(n-1) + f(3)*f(n-2) + ......f(n-2)*f(3) + f(n-1)*f(2)

f(n) = h(n-2)

 

類似問題:

在圓上選擇2n個點,將這些點成對連接起來使得所得到的n條線段不相交的方法數?

思路:以其中一個點爲基點,編號爲0,然後按順時針方向將其他點依次編號。那麼與編號爲0相連點的編號一定是奇數,否則,這兩個編號間含有奇數個點,勢必會有個點被孤立,即在一條線段的兩側分別有一個孤立點,從而導致兩線段相交。設選中的基點爲A,與它連接的點爲B,那麼AB將所有點分成兩個部分,一部分位於AB的左邊,另一部分位於AB的右邊。然後分別對這兩部分求解即可。

設問題的解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)

 

Cn = n*n 的方格地圖中,從一個角到另外一個角,不跨越對角線的路徑數;

4、給定節點組成二叉樹

給定N個節點,能構成多少種不同的二叉樹?(能構成hN)個)(這個公式的下標是從h(0)=1開始的)

思路:可以這樣考慮,根肯定會佔用一個結點,那麼剩餘的n-1個結點可以有如下的分配方式,T(0, n-1),T(1, n-2),...T(n-1, 0),設T(i, j)表示根的左子樹含i個結點,右子樹含j個結點。

設問題的解爲f(n),那麼

假設f(0) = 1,那麼f(1) = 1, f(2) = 2, f(3) = 5

f(n) = f(0)*f(n-1) + f(1)*f(n-2) + .......+ f(n-2)*f(1) + f(n-1)*f(0)

f(n) = h(n).

 

實例:

1描述:有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?

     思路:可以將持5元買票視爲進棧,那麼持10元買票視爲5元的出棧。這個問題就轉化成了棧的出棧次序數。由應用2的分析直接得到結果,

f(2n) = h(n)*n!*n!。(後面的*n!*n!爲進出棧的排列)

 

2、擁有 n+1 個葉子節點的二叉樹的數量爲h(n)

 

 

編程實例:

// 使用公式計算:h(n ) = h(n-1)*(4*n-2) / (n+1)

 

#include

#include

using namespace std;

//h(n ) = h(n-1)*(4*n-2) / (n+1)

int catelan1(int n)

{

    if(n==0) return 1;

    else return catelan1(n-1)*(4*n-2)/(n+1);

}

 

//h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

int catelan2(int n)

{

    int i,j,h[100];

    memset(h, 0, sizeof(h));

    h[0]=h[1]=1;

     for(i=2; i<=n; i++)

     for(j=0; j

         h[i] += h[j]*h[i-1-j];

     return h[n];

}

//h(n)=C(2n,n)/(n+1) (n=0,1,2,...)

int Cn(int n)

{

    int i,sum=1;

    for(i=1; i<=n; i++)

    sum*=i;

    return sum;

}

int catelan3(int n)

{

    return Cn(2*n)/Cn(n)/Cn(n)/(n+1);

}

int main()

{

    for(int i=0; i<=10; i++)

    cout<<"h("<<i<<"):"<<catelan1(i)<<endl;

}

 

運行結果:

h(0):1

h(1):1

h(2):2

h(3):5

h(4):14

h(5):42

h(6):132

h(7):429

h(8):1430

h(9):4862

h(10):16796

 

Process returned 0 (0x0)   execution time : 0.234 s

Press any key to continue.

公式3有點問題。。。

 

還有一種分級排列法,沒怎麼看明白。。。

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