1. 程式人生 > 其它 >C++ dp動態規劃經典問題-爬樓梯 [LeetCode 70]

C++ dp動態規劃經典問題-爬樓梯 [LeetCode 70]

(1)

假設你正在爬樓梯。需要 n階你才能到達樓頂。
每次你可以爬 12 個臺階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是一個正整數。

輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
1.  1 階 + 1 階 + 12.  1 階 + 23.  2 階 + 1 階

連結:https://leetcode-cn.com/problems/climbing-stairs

這裡參考@程式碼隨想錄的分析:

爬到第一層樓梯有一種方法,爬到二層樓梯有兩種方法。那麼第一層樓梯再跨兩步就到第三層 ,第二層樓梯再跨一步就到第三層。所以到第三層樓梯的狀態可以由第二層樓梯 和 到第一層樓梯狀態推匯出來,那麼就可以想到動態規劃了。

所以要定義一個一維陣列來記錄不同樓層的狀態,確定dp陣列以及下標的含義:dp[i]: 爬到第i層樓梯,有dp[i]種方法。

首先是dp[i - 1],上i-1層樓梯,有dp[i - 1]種方法,那麼再一步跳一個臺階不就是dp[i]了麼。

還有就是dp[i - 2],上i-2層樓梯,有dp[i - 2]種方法,那麼再一步跳兩個臺階不就是dp[i]了麼。

那麼dp[i]就是 dp[i - 1]與dp[i - 2]之和!所以dp[i] = dp[i - 1] + dp[i - 2] 。

由於dp[0]不確定意義,所以不做討論。

程式碼:

直接遞迴在n過大後,可能存在棧溢位的情況

int climbStairs(int
n) { if(n==2) return 2; if(n==1) return 1; return climbStairs(n-1)+climbStairs(n-2); }

比較常用的一種解法是:

int climbStairs(int n) {
        if (n <= 1) return n; // 因為下面直接對dp[2]操作了,防止空指標
        vector<int> dp(n + 1);
        dp[1] = 1;
        dp[2] = 2
; for (int i = 3; i <= n; i++) { // 注意i是從3開始的 dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n];

節省空間的話,有:

    int climbStairs(int n) {
        if(n<=2)
            return n;
        int i1=1,i2=2;
        int temp;
        for(int i=3;i<=n;i++)
        {
            temp=i1+i2;
            i1=i2;
            i2=temp;
        }
        return i2;
    }

(2)繼續深化,就是一步一個臺階,兩個臺階,三個臺階,直到 m個臺階,有多少種方法爬到n階樓頂

蕩塵滌汙,重整河山,便在今日