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

news2024/11/15 9:00:41

欢迎

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


前言

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


一、动态规划五部曲

  • 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.注意下标的映射关系。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

61. 旋转链表

61. 旋转链表 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 旋转链表 https://leetcode.cn/problems/rotate-list/ 完成情况&#xff1a; 解题思路&#xff1a; 参考代码&#xff1a; package 西湖算法题解_…

【C语言】指针进阶[中](函数指针、函数指针数组、指向函数指针数组的指针)

简单不先于复杂&#xff0c;而是在复杂之后。 目录 1. 函数指针 1.1 函数指针的用途 2. 函数指针数组 3. 指向函数指针数组的指针 1. 函数指针 这里的 * 可以省略: 因为函数指针本质上是一个指针&#xff0c;存储了一个函数的地址&#xff0c;因此可以通过函数指针调用对…

解锁虚拟人IP“悦小满”新玩法,怎么用动捕设备化身多重身份?

在数字时代&#xff0c;虚拟人IP成为文化产业与数字技术、数字平台相融合的产物。虚拟人IP是文化IP文化产业发展的新内核。 广东网络广播电视台顺应时代发展&#xff0c;推出了全球首个粤语虚拟偶像“悦小满”&#xff0c;具备着Z世代所喜爱的2.5次元的3D虚拟形象&#xff0c;…

React 企业级开发必备, 我来带你快速入门 !

目录 一、为什么我来安利你学习 React? 二、使用 React 的前置工作 三、简易 demo 学开发 3.1、jsx语法 3.2、函数式组件 demo 3.3、简单类组件定义 3.4、复杂类组件定义 3.4.1、state 写法一&#xff1a;复杂式 写法二&#xff1a;简便式 3.4.2、props 类型限制…

界面干净整洁的windows桌面清单软件有哪些

无论是工作还是日常生活&#xff0c;我们都有各种各样的任务需要完成。然而&#xff0c;如果不进行有效的规划和管理&#xff0c;很容易导致遗漏和拖延&#xff0c;影响工作效率。而一个界面干净整洁的Windows桌面清单&#xff0c;能够帮助我们更好地规划和安排待办事项&#x…

优雅编码:WebStorm引领你迈向开发巅峰

目录 引言WebStrom的优点WebStorm的缺点自用插件推荐总结&#xff1a; WebStorm 官网 引言 WebStorm 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它提供了许多功能和工具&#xff0c;帮助开发人员优雅编码。 因为我是一个前端开发工程师&#xff0c;…

力扣 -- 面试题 17.16. 按摩师

题目链接&#xff1a;面试题 17.16. 按摩师 - 力扣&#xff08;LeetCode&#xff09; 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 参考代码&#xff1a; class Solution { public:int massage(vector<int…

哪款恢复数据的软件好用,数据恢复成功率高吗

我们的日常工作中免不了出现误删或者因为系统崩溃而丢失重要的文件的情况&#xff0c;这些文件的丢失会对我们的工作生活造成或多或少的损失。其实我们可以利用一些专业的软件来恢复这些丢失的数据。 许多网友会有疑问&#xff0c;哪款恢复数据的软件好用&#xff0c;数据恢复成…

2021-04-29 VSC++:吻合日。

缘由https://bbs.csdn.net/topics/399168383 void 吻合日() {//缘由https://bbs.csdn.net/topics/399168383int n 0, n1 0, y 0, y1 0, h 0, h1 0,z 0, j 0, x 0, t 0;std::cin >> n >> y >> h;z 自适年一月一日周一值(n) h;y1 y; t 返回月的…

Devops之制品库平台实践-nexus

Devops之制品库平台实践-nexus 目录 本节实践 实战名称&#x1f498; 实践&#xff1a;配置Maven代理仓库(测试成功)-2022.6.7&#x1f498; 实践&#xff1a;创建Maven本地仓库&#xff08;依赖&#xff09;-2022.6.10(测试成功)&#x1f498; 实践&#xff1a;创建Raw本地仓…

Java模拟OPC Server服务器并创建节点代码实现

前言 模拟OPC Server服务器的方法除了使用KEPServerEX6软件以外&#xff0c;还可以使用java代码模拟启动一个opc server。下文详细讲解&#xff0c;如何使用java代码&#xff0c;实现模拟一个或者多个opc server服务器。 引入依赖 首先在Maven项目的pom.xml文件中引入所需的…

量水堰计的作用是什么有什么特点

水库大坝安全监测中&#xff0c;渗流监测是一个重要的组成部分。量水堰计作为一种测量流量的仪器&#xff0c;在渗流监测中起着至关重要的作用。其工作原理是&#xff0c;在进水口处设置量水堰&#xff0c;量水堰上安装有磁致伸缩液位传感器&#xff0c;可以实时记录通过量水堰…

【ARM】-IRQ 和 FIQ 异常中断处理程序的返回

文章目录 处理流程示例代码实现 处理流程 通常处理器执行完当前指令后&#xff0c;查询 IRQ 中断引脚及 FIQ 中断引脚&#xff0c;并且查看系统是否允许 IRQ 中断及 FIQ中断。 如果有中断引脚有效&#xff0c;并且系统允许该中断产生&#xff0c;处理器将产生 IRQ 异常中断或 …

自动化测试selenium篇(一)

一、自动化测试 1.1自动化测试介绍 自动化测试就相当于将人工测试手段进行转换&#xff0c;让代码去执行 1.2 自动化测试的分类 单元测试、接口测试、UI自动化测试 二、selenium介绍 2.1 selenium是什么 Selenium是web应用中基于UI的自动化测试框架 2.2 selenium的特点…

Redis的主从复制模式

主从复制就是Redis集群的策略 配从库不配主库&#xff1a;小弟可以选择谁是大哥&#xff0c;但大哥没有权利去选择小弟 读写分离&#xff1a;主机写&#xff0c;从机读 集群配置和搭建 1.将虚拟机中的CentOS(192.168.40.100)重新复制两份 2.将新复制的静态ip改一下,192.168.40.…

https 证书到期,手动更新

记录一下&#xff0c;因为 3 个月后还会用到的。。 1. 验证域名所有权&#xff08;在某个目录下放置指定文件验证&#xff09; http://172.245.xxx.xxx/.well-known/pki-validation/3C42D2093F4B0237224A95xxxxxxx.txt 2. 替换下载下来的证书文件 3. 检查&#x1f9d0; 喜欢或…

JMeter正则表达式提取器实践

目录 前言&#xff1a; apply to&#xff1a; 要检查的响应字段&#xff1a;样本数据源 引用名称&#xff1a; 正则表达式&#xff1a; 模板&#xff1a; 匹配数字&#xff1a; 缺省值&#xff1a; 前言&#xff1a; JMeter是一个流行的性能测试工具&#xff0c;它提供…

《Effective C++》 全书内容提炼总结

个人博客地址: https://cxx001.gitee.io 本文阅读说明 孔子云&#xff1a;“取乎其上&#xff0c;得乎其中&#xff1b;取乎其中&#xff0c;得乎其下&#xff1b;取乎其下&#xff0c;则无所得矣”。 对于读书求知而言&#xff0c;这句古训教我们去读好书&#xff0c;最好是…

【基础算法】穷举法

穷举法Exhaustive method是使用最广泛、设计最简单&#xff0c;同时最耗时的算法&#xff0c;也被称为暴力法、蛮力法Brute force method。 两数之和 给定一个整数数组array和一个目标值target&#xff0c;请在数组中找出和为目标值target的两个整数&#xff0c;并输出它们在数…

【PHP语言】医院安全(不良)事件报告系统源码

一、系统概述&#xff1a; 医院安全&#xff08;不良&#xff09;事件报告系统是一种用于医院管理和监管的工具&#xff0c;旨在帮助医疗机构识别、跟踪、分析和解决各种医疗安全事件&#xff0c;提高医疗质量和患者安全。 医院安全&#xff08;不良&#xff09;事件报告系统采…