对于动态规划问题,将拆解为如下五步曲
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
509.斐波那契数
思路:
-  确定dp数组(dp table)以及下标的含义:dp[i]的定义为:第i个数的斐波那契数值是dp[i] 
-  确定递推公式:状态转移方程 dp[i] = dp[i - 1] + dp[i - 2] 
-  dp数组如何初始化:dp[0] = 0,dp[1] = 1 
-  确定遍历顺序:从前到后遍历 
-  举例推导dp数组:推导一下,当N为10的时候,dp数组应该是如下的数列: 0 1 1 2 3 5 8 13 21 34 55 
class Solution:
    def fib(self, n: int) -> int:
        dp = [0 for _ in range(n+1)]
        if n < 1:
            return 0
        dp[0] = 0
        dp[1] = 1
        for i in range(2,n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]
70.爬楼梯
思路:
-  确定dp数组(dp table)以及下标的含义:dp[i]: 爬到第i层楼梯,有dp[i]种方法 
-  确定递推公式: dp[i] 可以有两个方向推出来。 首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。 还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。 
-  dp数组如何初始化:dp[0] = 1,dp[1] = 1 
-  确定遍历顺序:从前到后遍历 
-  举例推导dp数组: 
class Solution:
    def climbStairs(self, n: int) -> int:
        dp = [0 for _ in range(n+1)]
        if n == 0:
            return 0
        dp[0] = 1
        dp[1] = 1
        for i in range(2,n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]
746.使用最小花费爬楼梯
思路:
-  确定dp数组(dp table)以及下标的含义:dp[i]爬到楼顶的花费 
-  确定递推公式: dp[i - 1],到上i-1层楼梯,花费dp[i - 1],i-1到i花费dp[i - 1]+cost[i-1] dp[i - 2],上i-2层楼梯,花费dp[i - 2],i-2到i花费dp[i - 2]+cost[i-2] dp [i] = min(dp[i - 1]+cost[i-1],dp[i - 2]+cost[i-2]) 
-  dp数组如何初始化:dp[0] = 0,dp[1] = 0 **注意:**题目描述中明确说了 “你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。” 也就是说 从 到达 第 0 个台阶是不花费的,但从 第0 个台阶 往上跳的话,需要花费 cost[0]。 
-  确定遍历顺序:从前到后遍历 
-  举例推导dp数组: 
cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] ,来模拟一下dp数组的状态变化,如下:

class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        n = len(cost) 
        dp = [0 for _  in range(n+1)]
        if n < 1:
            return 0
        dp[0] = 0
        dp[1] = 0
        for i in range(2, n+1):
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
        return dp[n]



















