1. 程式人生 > >【動態規劃】爬樓梯問題

【動態規劃】爬樓梯問題

1.問題描述

一個人爬樓梯,每次只能爬1個或兩個臺階,假設有n個臺階,那麼這個人有多少種不同的爬樓梯方法

2.分析

如果n==1,顯然只有從0->1一種方法f(1)=1;
如果n==2,那麼有0->1->2、0->2兩種方法f(2)=2;
如果n==3,那麼可以先爬到第1階,然後爬兩個臺階,或者先爬到第二階,然後爬一個臺階,顯然f(3)=f(2)+f(1);
……
推廣到一般情況,對於n(n>=3)個臺階,可以先爬到第n-1個臺階,然後再爬一個臺階,或者先爬到n-2個臺階,然後爬2個臺階,因此有f(n)=f(n-1)+f(n-2)。
那麼動態規劃的遞推公式和邊界條件都有了,即:
這裡寫圖片描述

3.程式程式碼

根據遞推公式,可以寫如下程式碼輕鬆解決問題:

#include<stdio.h>
long long fun(int n);
int main()
{
    printf("%lld ",fun(80));
    return 0;
}
long long fun(int n)
{
    if(n==1)
        return 1;
    else if(n==2)
        return 2;
    else if(n>2)
        return fun(n-1)+fun(n-2);
}

注意:fun(80)的結果非常大,程式執行時間很長,測試的時候可以用小一點的數字測試。
雖然程式碼簡單,但是顯然這種方法實在是太耗時間了,遞迴函式多次重複計算中間結果。我們改進以下,開一個數組來儲存中間結果。

#include<stdio.h>
long long calc(long long step[],int n);
long long step[101]={0};
int main()
{
    int n;
    scanf("%d",&n);
    int i=1;
    for(i=1;i<=n;i++)
        printf("%lld ",calc(step,i));

    return 0;
}
long long calc(long long step[],int n)
{
    long long i;
    if(n<=0
) return 0; step[0]=1; step[1]=1; if(n>=2&&step[n-1]>0&&step[n-2]>0) { step[n] = step[n-1] + step[n-2]; return step[n]; } else if(n>=2) { for(i=2;i<=n;i++) step[i] = step[i-1]+step[i-2]; } return step[n]; }