文章目录

  • 动态规划之网格图模型(二)
    • LeetCode 931. 下降路径最小和
      • 思路
      • Golang 代码
    • LeetCode 2684. 矩阵中移动的最大次数
      • 思路
      • Golang 代码
    • LeetCode 2304. 网格中的最小路径代价
      • 思路
      • Golang 代码
    • LeetCode 1289. 下降路径最小和 II
      • 思路
      • Golang 代码
    • LeetCode 3418. 机器人可以获得的最大金币数
      • 思路
      • Golang 代码

动态规划之网格图模型(二)

今天我们继续学习动态规划当中的网格图模型。
在这里插入图片描述

LeetCode 931. 下降路径最小和

思路

题目中已经提到,下降路径可以从这一行当中的任何一个元素开始,也就意味着在一条路径上,某一行的某个元素的上一个元素是它正上方、左上方、右上方某个元素。根据这条性质,我们使用二维数组dp表示(i, j)这个位置的子路径和,据此我们可以写出状态转移方程:dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1], dp[i - 1][j + 1]) + matrix[i][j]。注意处理边界情况,也就是元素位于左边界和右边界时,左上方或右上方的元素取不到,因为如果取到的话数组就越界了。

最后取最后一行的最小值,就是最终答案。

Golang 代码

func minFallingPathSum(matrix [][]int) int {m, n := len(matrix), len(matrix[0])dp := make([][]int, m)for i := 0; i < m; i ++ {dp[i] = make([]int, n)}for i := 0; i < n; i ++ {dp[0][i] = matrix[0][i]}for i := 1; i < m; i ++ {for j := 0; j < n; j ++ {if j == 0 {dp[i][j] = min(dp[i - 1][j], dp[i - 1][j + 1]) + matrix[i][j]} else if j == n - 1 {dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j]) + matrix[i][j]} else {dp[i][j] = min(dp[i - 1][j -  1], dp[i - 1][j], dp[i - 1][j + 1]) + matrix[i][j]}}}return slices.Min(dp[m - 1])
}

LeetCode 2684. 矩阵中移动的最大次数

思路

这道题可以使用 DFS 或 BFS 来解决,也可以使用 DP 来解决。 具体来说,最开始我们可以从矩阵第一列的任何位置开始移动,每次只能移动到右、右上、右下三个位置,且移动到的位置需要满足那个位置的元素大于当前位置的元素。通过观察不难发现,能够在矩阵中移动的最大次数等于矩阵的总列数,也就是说,最大次数对应的移动方案就是从第一列移动到最后一列。

如果我们使用 DP,那么可以使用一个二维的数组dp来记录元素(i, j),是否是「可到达的」,因此dp保存的是 bool 值。初始状态下,第一列的所有元素都是可以到达的,所以我们令第一列的 bool 值都为 true。从第二列开始,我们判断每一行的元素是否可到达,判断的依据是当前元素左侧的那一列上是否有满足条件的元素使得从那个元素可以到达当前元素。

由于我们使用 DP 的思路来解题,因此应该反向思考,要到达(i, j),就需要(i, j - 1)(i - 1, j - 1)以及(i + 1, j - 1)当中的一个或多个满足grid[ni][nj] < grid[i][j],这样(i, j)才是可达的。

在遍历某一列的每一行之前,使用一个 bool 值reachable来判断这一列是否可达,如果这一列不可达,那么就没必要继续向右侧的列遍历了,直接返回答案即可。

如果所有列都可达,那么答案就是n - 1,其中n是列数。

Golang 代码

func maxMoves(grid [][]int) int {m, n := len(grid), len(grid[0])dp := make([][]bool, m)for i := 0; i < m; i ++ {dp[i] = make([]bool, n)}// 第一行都是可达的, 对第一行进行初始化for i := 0; i < m; i ++ {dp[i][0] = true}for j := 1; j < n; j ++ {var reachable bool = falsefor i := 0; i < m; i ++ {if dp[i][j - 1] && grid[i][j - 1] < grid[i][j] {dp[i][j] = truereachable = true} else if i >= 1 && dp[i - 1][j - 1] && grid[i - 1][j - 1] < grid[i][j] {dp[i][j] = truereachable = true} else if i <= m - 2 && dp[i + 1][j - 1] && grid[i + 1][j - 1] < grid[i][j] {dp[i][j] = truereachable = true}}if !reachable {return j - 1}}return n - 1
}   

LeetCode 2304. 网格中的最小路径代价

思路

这道题的题目描述非常的复杂,实际上这道题在说的就是从第一行出发,寻找一个到达最后一行的最小代价。最小代价保存在moveCost数组当中,moveCost[i][j]代表的含义就是从值为i的点出发到达下一行第j列的代价。为了更好地理解moveCost,我们以图中值为5的点为例,它在moveCost中的位置就是moveCost[5],由于它位于第一行,因此从它开始到达第二行的40的代价分别是143

讲清楚了问题描述,我们现在就可以开始着手解决问题。仍然使用网格图 DP 的思路来解决当前问题,具体来说,设置一个二维的数组dp,用来记录从「最后一行」开始到达(i, j)位置的最小代价。这里重点强调一下最后一行,因为我们要使用自底向上的思路来解决当前问题,最终的答案是dp[0]这一行的最小值。

dp[i][j]的构成有三部分,第一部分就是从它的下一行某个元素k到达(i, j)的路径代价c,第二部分是从下一行元素已经积累的代价dp[i + 1][k],第三部分是(i, j)本身的值grid[i][j]。汇总三部分可以得到状态转移方程:dp[i][j] = dp[i + 1][k] + c + grid[i][j]。需要再次强调的是,我们使用自底向上的方式来解决问题,所以答案是自底向上更新的。

Golang 代码

func minPathCost(grid [][]int, moveCost [][]int) int {m, n := len(grid), len(grid[0])dp := make([][]int, m)for i := 0; i < m; i ++ {dp[i] = make([]int, n)}// 自底向上, 因此先初始化最后一行的值dp[m - 1] = grid[m - 1]// 最后的答案是 dp 数组第一行的最小值for i := m - 2; i >= 0; i -- {for j := 0; j < n; j ++ {val := grid[i][j]dp[i][j] = math.MaxIntfor k, c := range moveCost[val] {// moveCost 记录的就是从 (i, j) 出发到达下一行第 k 列的那个位置的代价dp[i][j] = min(dp[i][j], dp[i + 1][k] + c)}dp[i][j] += val // 最后需要加上当前位置的值}}return slices.Min(dp[0])
}

LeetCode 1289. 下降路径最小和 II

思路

这道题目与普通版本的「最小路径下降和」比较相似,较大的变化在于当前(i, j)的和可以与上一行的任意列的值累加,且相邻行所选的列不能重复。

我们使用 DP 来解决问题,使用二维数组dp来记录(i, j)位置的最小路径和。由于该位置可以由上一行除j以外任意位置到达,因此我们使用第三重循环来寻找该行最小的路径和,累加得到答案即可。

最终的答案是最后一行的最小值。

Golang 代码

func minFallingPathSum(grid [][]int) int {m, n := len(grid), len(grid[0])dp := make([][]int, m)for i := 0; i < m; i ++ {dp[i] = make([]int, n)}dp[0] = grid[0]for i := 1; i < m; i ++ {dp[i] = grid[i]for j := 0; j < n; j ++ {var val int = math.MaxIntfor k := 0; k < n; k ++ {if j == k {continue}val = min(val, dp[i - 1][k])}dp[i][j] += val}}return slices.Min(dp[m - 1])
}

LeetCode 3418. 机器人可以获得的最大金币数

思路

使用网格图 DP 来解决该问题。每多一个约束条件,DP 数组就应该增加一个维度。对于本题而言,新增加的约束就是「最多可以感化两个单元格」,也就是「最多有两个单元格可以不选」。我们使用三维数组dp来解决问题。第一个和第二个维度对应的是网格图的维度,而第三个维度对应的是「选/不选」的约束。

对于前两个维度而言,(i, j)位置的答案可以由(i - 1, j)(i, j - 1)贡献得到。而对于第三个维度,由于题目已经限定「不选」的最大次数是 2,因此dp[i][j][0]指的就是全选的情况,dp[i][j][1]对应的就是有一次不选的情况,dp[i][j][2]对应的是有两次不选的情况。这一部分的状态更新可以详见代码。

Golang 代码

func maximumAmount(coins [][]int) int {m, n := len(coins), len(coins[0])dp := make([][][3]int, m + 1)for i := 0; i <= m; i ++ {dp[i] = make([][3]int, n + 1)}for i := 0; i <= m; i ++ {dp[i][0] = [3]int{math.MinInt / 2, math.MinInt / 2, math.MinInt / 2}}for i := 0; i <= n; i ++ {dp[0][i] = [3]int{math.MinInt / 2, math.MinInt / 2, math.MinInt / 2}}dp[0][1] = [3]int{}for i := 1; i <= m; i ++ {for j := 1; j <= n; j ++ {x := coins[i - 1][j - 1]dp[i][j][0] = max(dp[i - 1][j][0] + x, dp[i][j - 1][0] + x)dp[i][j][1] = max(dp[i - 1][j][1] + x, dp[i][j - 1][1] + x, dp[i - 1][j][0], dp[i][j - 1][0])dp[i][j][2] = max(dp[i - 1][j][2] + x, dp[i][j - 1][2] + x, dp[i - 1][j][1], dp[i][j - 1][1])}}return dp[m][n][2]
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React 编译器

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&#…

mac下通过anaconda安装Python

本次分享mac下通过anaconda安装Python、Jupyter Notebook、R。 anaconda安装 点击&#x1f449;https://www.anaconda.com/download&#xff0c; 点击Mac系统安装包&#xff0c; 选择Mac芯片&#xff1a;苹果芯片 or intel芯片&#xff0c; 选择苹果芯片图形界面安装&#x…

Pandas 技术解析:从数据结构到应用场景的深度探索

序 我最早用Python做大数据项目时&#xff0c;接触最早的就是Pandas了。觉得对于IT技术人员而言&#xff0c;它是可以属于多场景的存在&#xff0c;因为它的本身就是数据驱动的技术生态中&#xff0c;对于软件工程师而言&#xff0c;它是快速构建数据处理管道的基石&#xff1…

【循环神经网络RNN第一期】循环神经网络RNN原理概述

目录 &#x1f9e0; 什么是循环神经网络&#xff08;RNN&#xff09;&#xff1f;&#x1f501; RNN 的结构图&#x1f504; RNN 的“记忆”与问题RNN梯度推导 &#x1f9ec; LSTM&#xff1a;解决长期依赖问题&#x1f9f1; LSTM 的核心结构LSTM总结 参考 人类在思考的时候&am…

代码随想录算法训练营 Day60 图论Ⅹ Bellmen_ford 系列算法

图论 题目 94. 城市间货物运输 I Bellmen_ford 队列优化算法 SPFA 大家可以发现 Bellman_ford 算法每次松弛 都是对所有边进行松弛。 但真正有效的松弛&#xff0c;是基于已经计算过的节点在做的松弛。 本图中&#xff0c;对所有边进行松弛&#xff0c;真正有效的松弛&#…

Juce实现Table自定义

Juce实现Table自定义 一.总体展示概及概述 在项目中Juce中TableList往往无法满足用户需求&#xff0c;头部和背景及背景颜色设置以及在Cell中添加自定义按钮&#xff0c;所以需要自己实现自定义TabelList&#xff0c;该示例是展示实现自定义TableList&#xff0c;实现自定义标…

C++ set数据插入、set数据查找、set数据删除、set数据统计、set排序规则、代码练习1、2

set数据插入&#xff0c;代码见下 #include<iostream> #include<set> #include<vector>using namespace std;void printSet(const set<int>& s) {for (set<int>::const_iterator it s.begin(); it ! s.end(); it) {cout << *it <…

深度学习赋能图像识别:技术、应用与展望

论文&#xff1a; 一、引言​ 1.1 研究背景与意义​ 在当今数字化时代&#xff0c;图像作为信息的重要载体&#xff0c;广泛存在于各个领域。图像识别技术旨在让计算机理解和识别图像内容&#xff0c;将图像中的对象、场景、行为等信息转化为计算机能够处理的符号或数据 &am…

深入解析C++引用:从别名机制到函数特性实践

1.C引用 1.1引用的概念和定义 引用不是新定义⼀个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同⼀块内存空间。比如四大名著中林冲&#xff0c;他有一个外号叫豹子头&#xff0c;类比到C里就…

【从0-1的HTML】第1篇:HTML简介

1 HTML简介 HTML是用来描述网页的一种语言,是超文本标记语言的缩写(Hyper Text Markup Language),不属于编程语言的范畴&#xff0c;属于一种标记语言。 标记语言使用一套标记标签(Markup tag)&#xff0c;又称为标签,HTML就是使用标记标签来描述网页。 1.2 HTML标签 1、HTM…

vue+cesium示例:地形开挖(附源码下载)

基于cesium和vue绘制多边形实现地形开挖效果&#xff0c;适合学习Cesium与前端框架结合开发3D可视化项目。 demo源码运行环境以及配置 运行环境&#xff1a;依赖Node安装环境&#xff0c;demo本地Node版本:推荐v18。 运行工具&#xff1a;vscode或者其他工具。 配置方式&#x…

qwen大模型在进行词嵌入向量时,针对的词表中的唯一数字还是其他的?

qwen大模型在进行词嵌入向量时,针对的词表中的唯一数字还是其他的? Qwen大模型进行词嵌入向量时,针对的是词表中每个 Token 对应的唯一数字(Token ID) ,核心逻辑结合词表构建、嵌入过程展开 一、Qwen 词表与 Token ID Qwen 用 BPE 分词器(基于 tiktoken,以 cl100k 为…

动态规划-1143.最长公共子序列-力扣(LeetCode)

一、题目解析 对于给定了两个字符串中&#xff0c;需要找到最长的公共子序列&#xff0c;也就是两个字符串所共同拥有的子序列。 二、算法原理 1、状态表示 dp[i][j]&#xff1a;表示s1的[0,i]和s2的[0,j]区间内所有子序列&#xff0c;最长子序列的长度 2、状态转移方程 根…

互联网c++开发岗位偏少,测开怎么样?

通过这标题&#xff0c;不难看出问这个问题的&#xff0c;就是没工作过的。如果工作过&#xff0c;那就是不断往深的钻研&#xff0c;路越走越窄&#xff0c;找工作一般就是找原来方向的。没工作过的&#xff0c;那一般就是学生。 学生找什么方向的工作比较好&#xff1f; 学生…

推荐算法八股

跑路了&#xff0c;暑期0offer&#xff0c;华为主管面挂了&#xff0c;真幽默&#xff0c;性格测评就挂了居然给我一路放到主管面&#xff0c;科大迅飞太嚣张&#xff0c;直接跟人说后面要面华为&#xff0c;元戎启行&#xff0c;学了C后python完全忘了怎么写&#xff0c;挺尴尬…

Spring Boot微服务架构(九):设计哲学是什么?

一、Spring Boot设计哲学是什么&#xff1f; Spring Boot 的设计哲学可以概括为 ​​“约定优于配置”​​ 和 ​​“开箱即用”​​&#xff0c;其核心目标是​​极大地简化基于 Spring 框架的生产级应用的初始搭建和开发过程​​&#xff0c;让开发者能够快速启动并运行项目…

前端导入Excel表格

前端如何在 Vue 3 中导入 Excel 文件&#xff08;.xls 和 .xlsx&#xff09;&#xff1f; 在日常开发中&#xff0c;我们经常需要处理 Excel 文件&#xff0c;比如导入数据表格、分析数据等。文章将在 Vue 3 中实现导入 .xls 和 .xlsx 格式的文件&#xff0c;并解析其中的数据…

C++和C#界面开发方式的全面对比

文章目录 C界面开发方式1. **MFC&#xff08;Microsoft Foundation Classes&#xff09;**2. **Qt**3. **WTL&#xff08;Windows Template Library&#xff09;**4. **wxWidgets**5. **DirectUI** C#界面开发方式1. **WPF&#xff08;Windows Presentation Foundation&#xf…

刷leetcode hot100返航必胜版--链表6/3

链表初始知识 链表种类&#xff1a;单链表&#xff0c;双链表&#xff0c;循环链表 链表初始化 struct ListNode{ int val; ListNode* next; ListNode(int x): val&#xff08;x&#xff09;,next(nullptr) {} }; //初始化 ListNode* head new ListNode(5); 删除节点、添加…

软考 系统架构设计师系列知识点之杂项集萃(78)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;77&#xff09; 第139题 以下关于软件测试工具的叙述&#xff0c;错误的是&#xff08;&#xff09;。 A. 静态测试工具可用于对软件需求、结构设计、详细设计和代码进行评审、走查和审查 B. 静…