1. 程式人生 > >[ACM] hdu 2067 小兔的棋盤(卡特蘭數Catalan)

[ACM] hdu 2067 小兔的棋盤(卡特蘭數Catalan)

小兔的棋盤

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5814    Accepted Submission(s): 3186


Problem Description 小兔的叔叔從外面旅遊回來給她帶來了一個禮物,小兔高興地跑回自己的房間,拆開一看是一個棋盤,小兔有所失望。不過沒過幾天發現了棋盤的好玩之處。從起點(0,0)走到終點(n,n)的最短路徑數是C(2n,n),現在小兔又想如果不穿越對角線(但可接觸對角線上的格點),這樣的路徑數有多少?小兔想了很長時間都沒想出來,現在想請你幫助小兔解決這個問題,對於你來說應該不難吧! Input 每次輸入一個數n(1<=n<=35),當n等於-1時結束輸入。 Output 對於每個輸入資料輸出路徑數,具體格式看Sample。 Sample Input 1 3 12 -1 Sample Output 1 1 2 2 3 10 3 12 416024 Author Rabbit Source

解題思路:

卡特蘭數:

1 通項公式:h(n)=C(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!)

2遞推公式:h(n)=((4*n-2)/(n+1))*h(n-1); h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)*h(0).

3前幾項為:h(0)=1,h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,......

程式碼採用第二個公式。本題結果為2*C[n]

參考資料:

程式碼:

#include <iostream>
#include <string.h>
using namespace std;

const int N=36;
long long c[N];

void Catalan()
{
    memset(c,0,sizeof(c));
    c[0]=c[1]=1;
    for(int i=2;i<=35;i++)
        for(int j=0;j<i;j++)
    {
        c[i]+=c[j]*c[i-j-1];
    }
}



int main()
{
    Catalan();
    int n;
    int t=1;
    while(cin>>n&&n!=-1)
    {
        cout<<t++<<" "<<n<<" "<<2*c[n]<<endl;
    }
    return 0;
}