【动态规划上分复盘】下降路径最小和|礼物的最大价值

欢迎

  • 前言
  • 一、动态规划五部曲
  • 二、下降路径最小和
    • 思路:动态规划解法
      • 具体代码如下
  • 三、礼物的最大价值
    • 思路:动态规划
      • 具体代码如下:
  • 总结


前言

本文主要讲述动态规划思路的下降路径最小和以及礼物的最大价值两道题。


一、动态规划五部曲

  • 1.确定状态表示(确定dp数组的含义)
  • 2.确定状态转移方程(确定dp的递推公式)
  • 3.确定如何初始化(初始化要保证填表正确)
  • 4.确定遍历顺序
  • 5.返回值

二、下降路径最小和

点我直达
在这里插入图片描述

思路:动态规划解法

  • 1.确定状态表示,即确定dp数组的含义。

    • 写动态规划的题目,确定状态表示是最重要的一步,如何确定呢?往往需要经验+题目描述,就需要大量的动态规划问题基础。
      在本题中,我们需要使用二维dp数组来表示下降路径,所以dp数组的含义是:
      第[i,j]位置的最小下降路径为dp[i][j]。
  • 2.确定状态转移方程(确定递推公式)

    • 根据题目描述,第[i,j]位置是由第[i-1,j-1],[i-1,j],[i-1,j+1]三个位置的任意一个往下走得来,如下图。
      在这里插入图片描述
      所以我们可以确定,dp[i][j]一定与dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1]有关。
      我们再回顾dp数组的含义:dp[i][j] :第[i,j]位置的最小下降路径为dp[i][j]
      所以下降到第[i,j]的位置时,一定是由[i-1,j-1],[i-1,j],[i-1,j+1]三个位置的对于的最小dp值+当前位置的路径。
      即:dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+ob[i][j] ,其中ob为题目给出的二维数组。
  • 3.如何初始化

    • 细心的小伙伴会发现,第一行的数据,dp[0][j]是如何推导的呢?如果仅仅开辟题目给出的ob数组大小的dp数组空间,是无法初始化完全的。所以我们给出了一个多开辟虚拟空间的解决方案。如下图:
      在这里插入图片描述
      我们多开一行两列的空间,这样就满足了任意位置都能直接被便利到。
      但开辟虚拟空间需要注意两个问题:
      1.虚拟位置的初始化必须保证原dp数组正确。
      2.注意下标的映射关系。
      • (1)我们应该初始化第一行虚拟空间为0,这样保证了原dp数组的初始化不受影响。
        再初始化第一列和第n+1列为正无穷大。
        在这里插入图片描述

以图中数字为例,第[i-1,j-1]位置,也就是左上角位置是虚拟开辟出来的,所以必须要保证这个位置初始化的时候不能影响原数组的初始化。所以我们应该在这个虚拟位置初始化成正无穷大。就保证永远取不到这个地方。

      • (2)注意下标的映射关系,以上图为例,
        dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+ob[i-1][j-1] ,注意这里是+ob[i-1][j-1]而不是+ob[i][j],因为虚拟数组多开了一行两列,所以整体的元素都往右下角挪了一个位置,所以找原位置是必须回到左上角。
        在这里插入图片描述
  • 4.确定遍历顺序

    • 根据上述描述,和递推公式,可以知道我们只能从上往下进行遍历。
  • 5.返回值

    • 当遍历到最后一行时,我们应该知道,题目要求返回下降路径最小和,在最后一行中,每一个元素都是从上往下的下降路径最小的数,所以我们应该比较这最后一行元素中的最小值,返回即可。

具体代码如下

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& ob) 
    {
        //1.确定dp[i][j]的含义:下降到i,j位置的最小路径为dp[i][j]
        //2.递推公式:
        //dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+ob[i][j]        
        //3.初始化dp数组,多开一行,两列的虚拟空间,全部初始化为0
        //对虚拟空间的要求:1.里面的值要保证后面填表正确
        //2.要注意下标的映射
        //4.遍历顺序,只能从上到下遍历。
        //5.返回值,返回最后一行的最小值
        int n = ob.size();
        vector<vector<int>> dp(n+1,vector<int>(n+2,0));
        for(int i = 1;i<=n;i++)
        {
            dp[i][0] = INT_MAX;
            dp[i][n+1] = INT_MAX;
        }
//        vector<vector<int>> dp(n+1,vector<int>(n+2,INT_MAX));
        //第一行全部初始化成0,但是第一列和最后一列的第二行开始,就初始化成正无穷大
        // for(int i = 0;i< n+2;i++)
        // {
        //     dp[0][i] = 0;
        // }

        for(int i = 1;i<= n ;i++)
        {
            for(int j = 1;j<= n;j++)
            {
                dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i-1][j+1]))+ob[i-1][j-1];        
            }
        }
        int ret = INT_MAX;
        //遍历dp表的最后一行,选出最小值
        for(int i = 1;i<=n;i++)
        {
            ret = min(ret,dp[n][i]);
        }
    }
};

时间复杂度O(n^2), 空间复杂度O(n^2)


三、礼物的最大价值

点我直达~

在这里插入图片描述

思路:动态规划

  • 1.状态表示(确定dp数组的含义)
    根据经验和题目描述可知,
    dp[i][j]表示:到达第[i,j]位置拿到的礼物最大价值为dp[i][j].
  • 2.状态转移方程(确定递推公式)
    在这里插入图片描述

由图可知,走到第[i,j]位置一定是由它的上方往下走一步或者它的左侧往右走一步得来。所以dp[i][j]一定跟dp[i-1][j]和dp[i][j-1]有关。
再回顾一下dp数组的含义:到达第[i,j]位置拿到的礼物最大价值为dp[i][j]
那么由此我们可以确定递推公式:
dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + grid[i][j],其中grid是题目给出的数组。
可以发现本道题的思路与上一题类似。

  • 3.如何进行初始化
    有了上道题目的经验,我们发现,第一行的元素无法初始化,因为它没有上方的元素和左方的元素。所以我们应该多开辟一行一列的虚拟数组,如下图:
    在这里插入图片描述
    同理:需要注意两个问题,
    1.虚拟位置的初始化必须保证原dp数组正确。
    2.注意下标的映射关系。

所以我们应该初始化成0,这样在虚拟空间不会被选中,对原数组不产生影响。

那么下标的映射关系也是如此:
在这里插入图片描述
假如对想求出图中位置的dp值,应该为:
dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + grid[i-1][j-1],因为我们多开了一行一列的数组,所以这里原数组整体往右下角移动了一位,要找到原来的值,需要挪动回到左上角查找。

  • 4.确定初始化顺序
    由上面的分析可知,我们应该从上往下初始化,从左往右初始化。

  • 5.返回值

  • 返回右下角的值即可。

具体代码如下:

class Solution {
public:
    int maxValue(vector<vector<int>>& grid) 
    {
        int m = grid.size();
        int n = grid[0].size();
        vector<vector<int>>dp(m+1,vector<int>(n+1));
        for(int i = 1;i<=m;i++)
        {
            for(int j = 1;j<=n;j++)
            {
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + grid[i-1][j-1];
            }
        }
        return dp[m][n];
    }

};

时间复杂度O(m*n),空间复杂度O(m*n)

总结

今天学到了一个动态规划的点:多开辟一块空间,使得初始化变得更为简单,但是也要注意两个点:
1.虚拟位置的初始化必须保证原dp数组正确。
2.注意下标的映射关系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/34960.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux【系统学习】(shell篇)

第 1 章 Shell 概述 1&#xff09;Linux 提供的 Shell 解析器有 Ubuntu 使用的是dash 2&#xff09;bash 和 sh 的关系 3&#xff09;Centos 默认的解析器是 bash 第 2 章 Shell 脚本入门 1&#xff09;脚本格式 &#xff08;结尾不是必须以 .sh 结尾&#xff0c;只是为了区…

ModaHub魔搭社区:基于 Amazon EKS 搭建开源向量数据库 Milvus

目录 01 前言 02 架构说明 03 先决条件 04 创建 EKS 集群 05 部署 Milvus 数据库 06 优化 Milvus 配置 07 测试 Milvus 集群 08 总结 01 前言 生成式 AI&#xff08;Generative AI&#xff09;的火爆引发了广泛的关注&#xff0c;也彻底点燃了向量数据库&…

【网络原理之三】应用层协议HTTP和HTTPS

HTTP什么是HTTP工作过程协议格式协议内容HTTP请求MethodURLURL的encode和decode Version请求报头请求正文 HTTP响应状态码响应报头 HTTPSHTTPS执行过程加密对称加密非对称加密 证书 HTTP 什么是HTTP HTTP&#xff1a;超文本传输协议。是一种应用非常广泛的应该层协议。 所谓 “…

图片加载失败捕获上报及处理

图片加载失败捕获上报及处理 前端页面中加载最多的静态资源之一就是图片了&#xff0c;当出现图片加载失败时&#xff0c;非常影响用户体验。这时候我们就需要对图片是否成功加载进行判断&#xff0c;并对图片加载失败进行处理。 图片加载监听 单个捕获 HTML中的img标签可以…

集群 第一章

目录 1.群集的含义 2.群集分类 3.群集架构 4.负载调度工作模式 5.lvs 虚拟服务器 6.nat 模式 lvs 负载均衡群集部署 7.总结 1.群集的含义 由多台主机构成&#xff0c;但对外只表现为一个整体&#xff0c;只提供一个访问入口&#xff08;域名与IP地址&#xff09;&#…

威胁和漏洞管理增强远程 IT 安全性

威胁和漏洞管理是保护组织设备和数据的主动方法。它可以帮助管理员识别漏洞并检查安全设置是否薄弱。通过使用此方法&#xff0c;可以在任何弱点成为安全漏洞之前对其进行修复。 对远程威胁和漏洞管理工具的需求 随着越来越多的员工远程工作&#xff0c;网络攻击的可能性也在…

计算机网络————网络层

文章目录 网络层设计思路IP地址IP地址分类IP地址与硬件地址 协议ARP和RARPIP划分子网和构造超网划分子网构造超网&#xff08;无分类编址CIDR&#xff09; ICMP 虚拟专用网VPN和网络地址转换NATVPNNAT 网络层设计思路 网络层向上只提供简单灵活的、无连接的、尽最大努力交付的数…

基于django的数据可视化展现

今天给大家简单分享一下一个基于python的django的框架写的一个数据可视化的项目。 主要涉及技术&#xff1a;django基础&#xff0c;python基础&#xff0c;前端&#xff08;html&#xff0c;echars&#xff09;基础。 这个项目自然而然是基于python逻辑语言处理的&#xff0…

CSDN创作常用操作说明

CSDN创作 目录标题文本样式列表图片连接代码表格UML图Mermaid流程图Flowchart流程图classDiagram类图快捷键 目录 创建目录的方式&#xff1a; [TOC](目录)标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题文本样式 **加粗文本** ~…

第一章 Android 基础--开发环境搭建

文章目录 1.Android 发展历程2.Android 开发机器配置要求3.Android Studio与SDK下载安装4.创建工程与创建模拟器5.观察App运行日志6.环境安装可能会遇到的问题7.练习题 本专栏主要在B站学习视频&#xff1a; B站Android视频链接 本视频范围&#xff1a;P1—P8 1.Android 发展历…

Springboot整合mybatisplus实战

Springboot整合mybatisplus&#xff0c;纯后端&#xff0c;验证结果是通过postman调用的&#xff0c;记录一下 1、建表语句以及初始化数据脚本 CREATE TABLE tbl_book (id int NOT NULL AUTO_INCREMENT,type varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT…

Nginx 安装 headers-more-nginx-module 扩展,隐藏www服务信息

通过Ubuntu APT安装的Nginx默认是没有扩展的&#xff0c;所以需要手动安装才可以。本文主要分享如何在 APT 安装 Nginx 的环境中安装 headers-more-nginx-module 扩展&#xff0c;隐藏www服务信息。 1、起因 今天收到一个高危漏洞的警告&#xff0c;该漏洞大意为&#xff1a;…

Kubernetes 服务发布方式(蓝绿发布、灰度发布和滚动发布)

目录 一、三种常用的项目发布方式1.1 蓝绿发布1.2 灰度发布&#xff08;金丝雀发布&#xff09;1.3 滚动发布 二、金丝雀的方式升级发布实验三、总结 一、三种常用的项目发布方式 应用程序升级面临最大挑战是新旧业务切换&#xff0c;将软件从测试的最后阶段带到生产环境&…

阿里云国际站:为什么当初很多人不看好的阿里云做起来了?

标题&#xff1a;为什么当初很多人不看好的阿里云做起来了&#xff1f;   为什么人们曾经对阿里云的前景充满疑虑&#xff0c;而它现如今却成就了一番事业&#xff1f;这是个我们应当深思的议题。让我们共同走进阿里云的成长之旅&#xff0c;寻求答案的启示。   在阿里云初…

hive关联键 NULL 关联 NULL

结论&#xff1a;关联键 NULL NULL时&#xff0c;不进行关联&#xff0c;即两表关联失败 案例如下&#xff1a; 表A 表B 表A 关联 表B selecta.id as a_id,a.name as a_name,b.id as b_id,b.name as b_name from表A a left join表B b on a.id b.id …

适用于Vue 3的最佳开源分页库

从头开始实现分页可能是一项耗时的任务&#xff0c;需要大量的精力和资源。幸运的是&#xff0c;有几个伟大的开源库可以简化这个过程&#xff0c;提高你的效率。使用分页库可以节省你的时间和精力&#xff0c;使你能够专注于建立你的应用程序的其他更重要的功能。 在这篇文章…

分布式负载均衡 Ribbon

一、Ribbon简介 是Netfix发布的负载均衡&#xff0c;Eureka一般配合Ribbon进行使用&#xff0c;基于HTTP和TCP的客户端负载均衡工具。 只有负载均衡的能力&#xff0c;不具有发送请求的能力&#xff0c;要配合服务通信组件。 RestTemplate 针对各种类型的 HTTP 请求都提供了相…

《Java核心卷1》怎么样?读1,2章草记 | 第12版

文章目录 《Java核心技术卷 一》第一章 概述第二章 Java编程环境 图书推荐 《Java核心技术卷 一》 第一章 概述 前言&#xff1a;本书与一些”0基础入门“的书定位感觉是不太一样的&#xff0c;可能就像书名所说&#xff0c;是”核心技术“叭。书中经常将Java语言与 c 进行对比…

什么是内存溢出,什么是内存泄漏?

文章目录 一、什么是内存溢出&#xff1f;二、什么是内存泄漏&#xff1f;三、如何避免&#xff1f; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、什么是内存溢出&#xff1f; 假设我们 JVM 中可用的内存空间只剩下 3M&#xff0c;但是我们要创…