返回顶部

动态规划学习入门(小白零基础)

动态规划学习入门(小白零基础)

基础概念

  1. 如果某一问题可拆解成若干重叠子问题,即可用动态规划解决。

重叠子问题:比如斐波那契数列F(n)可分解成F(n-1)+F(n-2),而F(n-1)又可继续向下分解,而分解的过程相同,这就是重叠子问题。

  1. 在解决过程中不可避免的会遇到公式,用dp数组去解答问题,而这就需要明确dp数组在题目中的定义。

比如斐波那契数列求F(5),公式为F(n) = F(n-1)+F(n-2);

我们明确:dp[n]的定义为F(n)的值,dp(n) = dp(n-1)+dp(n-2);

思路入门

  1. 确定dp数组以及下标的含义
  2. 确定递推公式(dp数组表达)
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 如果没通过,则举例debug查错。

例题分析

[leetcode原题:使用最小花费爬楼梯](746. 使用最小花费爬楼梯 - 力扣(LeetCode))

题目描述:

​ 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

​ 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

​ 请你计算并返回达到楼梯顶部的最低花费。

示例:

示例1:

输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。

  • 支付 15 ,向上爬两个台阶,到达楼梯顶部。
    总花费为 15 。

示例2:

输入:cost = [1,100,1,1,1,100,1,1,100,1]
输出:6
解释:你将从下标为 0 的台阶开始。

  • 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
  • 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
  • 支付 1 ,向上爬一个台阶,到达楼梯顶部。
    总花费为 6 。

解题思路:

  • 首先,题目里说cost[i]是从第i阶向上爬的费用,从示例里我们能看出,真正的楼梯阶数是cost数组的长度+1。
  • 我们可这样想到达楼梯顶部和什么有关系?当然是和顶部的下一阶和下下一阶有关系了,因为这是到达顶部的两种方式(题目里说可一步爬一个或两个台阶)。所以,我们设一共有n阶,爬到顶部费用为dp[n],我们要找的是它和dp[n-1],dp[n-2]的递推关系。

方法:

​ 方法有两种,这里都以Java为编程语言实现!

方法一:

​ 我们把dp[n]看成是爬到第n阶楼梯所要付的费用,而要爬到n阶,只有两种选择,就是从n-1阶和n-2阶,因为说最小,所以取两者之间的最小值。

​ 递推公式:dp[n] = min{dp[n-1]+cost[n-1],dp[n-2]+cost[n-2]}

​ 初始化:dp[0] = 0; dp[1] = 0;也就是一开始的这两个起始台阶不花钱,毕竟我只是登上,还没往上爬呢。

遍历顺序:一阶一阶往上求

代码实现:

class Solution {
    public static int minCostClimbingStairs(int[] cost) {
        int length = cost.length;
        int[] dp = new int[length+1];
        dp[0] = 0;
        dp[1] = 0;
        for(int i = 2;i<=length;i++){
            //定义 dp[i]:到达第i层台阶所花费的最小费用
            //比较条件出问题了!不应该比dp,因为dp[i-1]和dp[i-2]到达dp[i]还要花钱
            if(dp[i-1] + cost[i-1] < dp[i-2] + cost[i-2]){
                dp[i] = dp[i-1] + cost[i-1];
            }else{
                dp[i] = dp[i-2] + cost[i-2];
            }
        }
        return dp[length];
    }
}

方法二:

​ 我们把dp[n]看成是从第n阶往上爬要付的费用。

​ 递推公式:dp[n] = min{dp[n-1],dp[n-2]} + cost[n]

​ 初始化:dp[0] = cost[0]; dp[1] = cost[1];

遍历顺序:一阶一阶往上求

代码实现:

class Solution {
    public static int minCostClimbingStairs(int[] cost) {
        int length = cost.length;
        int[] dp = new int[length+1];
        dp[0] = cost[0];
        dp[1] = cost[1];
        
        for(int i = 2;i<length;i++){
            //注意这里是i<length,没有 = ,因为爬到顶阶就好了,不需要计算从顶阶往上爬的费用鸭
            if(dp[i-1]< dp[i-2]){
                dp[i] = dp[i-1] + cost[i];
            }else{
                dp[i] = dp[i-2] + cost[i];
            }
        }
        return dp[length-1]<dp[length-2]?dp[length-1]:dp[length-2];
    }
}
posted @ 2022-11-01 15:12  哲里  阅读(94)  评论(0编辑  收藏  举报