一組簡單一點的題目(六) B – 小兔的棋盤

haixinjiazu發表於2019-05-10

題目:B – 小兔的棋盤
小兔的叔叔從外面旅遊回來給她帶來了一個禮物,小兔高興地跑回自己的房間,拆開一看是一個棋盤,小兔有所失望。不過沒過幾天發現了棋盤的好玩之處。從起點(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

思路:這個題要特別注意一下里面有個要求即不能越過對角線!,所以可以分開處理,即將其分成上半邊和下半邊。只需要求出一個半邊,之後乘2即可。
這個題一開始我想進行組合來著,但是後來發現因為不能越過對角線,所以不可以進行組合,所以就用類似斐波那契數列進行,即每次到一個格子的的方式的數量由走到下一個格子和走到左一個格子的方式的數量之和。而對角線因為特殊所以要單獨處理,即走到對角線的方式的數量僅有下邊一個格子決定,每次都要算到(n,n),即每次迴圈儲存的時候都要到(i,i);

新技巧:這個類斐波那契數列存數的方式早就接觸到,但這個是一種可以用的情況,即行走的步數的問題,即從這裡走怎麼走到另一個問題,所以從每一步的種類數量由前一步還是前幾步決定。
所以,總得來說就是,這種走路方式和數量的問題都可以嘗試用類斐波那契數列處理,前提必須要有前後關係才行!!

程式碼:

#include<iostream>
#include<cstring>

using namespace std;
long long a[37][37];
int main()
{
    int i,j,n;
    memset(a,0,sizeof(a));
    for(i=1;i<36;++i){
        a[i][0]=1;
        for(j=1;j<i;++j){
            a[i][j]=a[i-1][j]+a[i][j-1];
        }
        a[i][i]=a[i][i-1];
    }
    int num=0;
    while(cin >> n&&n!=-1){
            num++;
        cout << num << " " << n << " "<< 2*a[n][n] << endl;
    }
    return 0;
}

相關文章