首页 > 其他分享 >动态规划学习入门(小白零基础)

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

时间:2022-11-01 15:24:58浏览次数:82  
标签:台阶 入门 int 上爬 小白 cost 下标 动态 dp

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

基础概念

  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];
    }
}

标签:台阶,入门,int,上爬,小白,cost,下标,动态,dp
From: https://www.cnblogs.com/zheli1/p/16847804.html

相关文章

  • 学习笔记——动态 dp
    前言好消息,CSP-St4出DDP,并且有的人场上为了调T3的假算没写。。。概述其实是个挺简单的东西,就是如果一道题可以通过dp轻松解决,但是题目加上了每次询问修改一些信......
  • 动态规划-回文串
    回文串是从左到右和从右到左读起来一样的字符串,变种还有回文子序列,区别就是字符可以不连续。求回文串个数、最长回文串、最长回文序列也是典型的二维动态规划问题。我们......
  • 动态规划-公共子序列
    公共子序列是二维动态规划的典型问题,一般用了求两个字符串的相似程度。我们看一个案例:案例1:给定两个字符串 text1和 text2,返回这两个字符串的最长公共子序列的长度......
  • 阿里云配置负载均衡快速入门
    慎选监听配置的高级配置“开启会话保持”功能,单机测试负截均衡,看不到调度IP切换效果负载均衡从诞生到现在也随着网络业务的变化而不断的进化,逐渐发展成为现在云化的负......
  • 动态规划-子序列
    子序列是序列的一部分,元素可以不连续。子串是字符串的一部分,必须连续。求子序列的和、连续递增子序列都是经典的一维动态规划问题。这一类题目都有差不多的思路,我们看案......
  • Logstash 入门实战(3)--input plugin 介绍
    本文主要概述Logstash的一些最受欢迎的输入插件,以大致了解Logstash的用途;相关的环境及软件信息如下:CentOS 7.9、Logstash8.2.2。1、什么是Logstashinput插件Logsta......
  • AJAX基础+Axios快速入门+JSON使用+综合案例
    目录1、AJAX1.1概述1.1.1作用1.1.2同步和异步1.2快速入门1.2.1服务端实现1.2.2客户端实现1.3案例1.3.1需求1.3.2分析1.3.2后端实现1.3.3前端实现2、Axios异步......
  • 【QT】创建动态链接库及使用
    创建动态链接库创建一个项目选择library的C++库,下一步。选择共享库,输入动态库的名字,选择创建路径,下一步选择编译环境,下一步选择QTCore模块,该模块提供核心的非图......
  • node2_动态路径拼接错误问题
      如果使用相对路径,不在当前目录下通过其他目录来找到这个JS运行就会报错,当我们使用fs模块来操作文件时,我们如果使用相对路径的话,很容易出现路劲动态拼接错误的情况,......
  • PhantomJS入门使用
    概述​​官网​​​,​​GitHub​​​,​​下载地址​​​简介:一个基于webkit的JSAPI。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JS代码。任何你可以......