【动态规划】【路径问题】下降路经最小和、最小路径和、地下城游戏

news2024/10/21 5:42:28

4. 下降路径最小和

931. 下降路径最小和
image.png|548

算法原理

  1. 确定状态表示

    • dp[i][j] 表示:到达 [i, j] 位置,最小的下降路径
  2. 状态转移方程

  • dp[i][j]

    • [i-1, j-1] 到达 [i, j] ==> dp[i-1][j-1] + m[i][j]
    • [i-1, j] 到达 [i, j] ==> dp[i-1][j] + m[i][j]
    • [i-1, i+1] 到达 [i, j] ==> dp[i-1][j+1] + m[i][j]
  • dp[i][j] = min(上面三个) + m[i][j]

  1. 初始化
    • 目的是为了让我们再填表的过程中不会出现越界的情况

里面的值,要保证后面的填表是正确的
image.png

  • 绿星的地方都可能会越界
  • 进行绿框范围的虚拟节点构造

  • 虚拟出的第一行全部填 0,就可以保证原表的第一行都是 0
  • 但从原表的第二行开始,每个格子都是取前三者之间的最小值,所以下面虚拟的节点就不能填最小的值 0 了,不然每个格子都是 0。所以都取正无穷大

下标的映射

  • 整个表向右下移动了一个单位长度
  • (0, 0)——>(1, 1)

在初始化的时候,可以把所有虚拟出的节点都设为 +∞,然后将第一行改为 0 就可以了

  1. 填表顺序

    • 从上往下
  2. 返回值

    • 这里不是返回 dp[m][n] 的值
    • 返回 dp 表中最行一行的最小值

代码编写

public int minFallingPathSum(int[][] matrix) {  
    //1. 创建 dp 表  
    int n = matrix.length;  
    int[][] dp = new int[n+1][n+2];  
  
    //2. 初始化  
    for (int i = 1; i <= n; i++) {  
        //第一列和最后一列  
        dp[i][0] = dp[i][n+1] = Integer.MAX_VALUE;  
    }  
  
    //3. 填表  
    for (int i = 1; i <= n; i++) {  
        for (int j = 1; j <= n; j++) {  
            dp[i][j] = Math.min(dp[i-1][j], 
            Math.min(dp[i-1][j], dp[i-1][j+1])) + matrix[i-1][j-1];  
        }  
    }  
    int ret = Integer.MAX_VALUE;  
    for (int i = 1; i <= n; i++) {  
        ret = Math.min(ret, dp[n][i]);  
    }  
    return ret;  
}
  • 取最值只能两个进行比较
  • 注意无穷值的写法

时间复杂度:n*n(两个 for 循环)
空间复杂度:n*n(弄了个二维 dp 表)

5. 最小路径和

64. 最小路径和
image.png|589

算法原理

  1. 确定状态表示

    • dp[i][j] 表示:到达 [i, j] 位置时,最小路径和
  2. 状态转移方程

  • dp[i][j]
    • [i-1, j] 走过来==> dp[i-1][j] + g[i][j]
    • [i, j-1] 走过来==> dp[i][j-1] + g[i][j]
    • `dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + g[i][j]
  1. 初始化
  • 因为是取最小值,所以虚拟的节点要小,以免被误取
  • 但起点需要是 0,所以它左边和上面的虚拟节点 dp[0][1]dp[1][0] 需要是 0
  1. 填表顺序

    • 从上往下
    • 从左往右
  2. 返回值

    • 返回 dp[m][n]

代码编写

public int minPathSum(int[][] grid) {  
    //1. 创建 dp 表  
    int m = grid.length;  
    int n = grid[0].length;  
    int[][] dp = new int[m+1][n+1];  
  
    //2. 初始化  
    for (int i = 0; i <= n; i++)  
        dp[0][i] = Integer.MAX_VALUE;  
      
    for (int i = 0; i <= m; i++)   
        dp[i][0] = Integer.MAX_VALUE;  
     
    dp[0][1] = dp[1][0] = 0;  
  
    //3. 填表  
    for (int i = 1; i <= m; i++) {  
        for (int j = 1; j <= n; j++) {  
            dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) + grid[i-1][j-1];  
        }  
    }  
    return dp[m][n];  
}

6. 地下城游戏

174. 地下城游戏
image.png|508

算法原理

  1. 确定状态表示
    • dp[i][j] 表示:从 [i, j] 位置出发,到达终点,所需的最低初始健康点数

这里不能以 [i, j] 为终点构建状态表示,

  1. 状态转移方程
  • dp[i][j],此时的点数必须要>=下一个要到的地方 dp 值
    • 从此处往右走,x+d[i][j] >= dp[i][j+1],所以 x >= dp[i][j+1] - d[i][j] 即可
    • 从此处往下走,同理 x >= d[i+1][j] - d[i][j] 即可

如果 d[i][j] 太大,就是说在那一格有个很大的血包。减完之后就变成一个负值了(你是一个负血的状态,通过这个格子之后也能顺利通过),这是不符合逻辑的。

  • 所以我们要把 dp[i][j]1 放在一起取一下 max
  • 如果算出来是负数,就更新为 1
  • 如果是大于等于 1 的数,就保持
  1. 初始化
    image.png|480

我们关注的是格子的下面和右边的状态,所以可能会越界的是最下面一行和最右边一行

  • 我们在最下面和最右边添加辅助节点
  • 此时就不用考虑下标映射关系

里面的值,需要保证后续的填表是正确的

  • 我们看原表终点格,要走出去,终点最少需要 1 点血量
  • 所以只需要把终点下面和右边的格子置为 1 就可以了
  • 其余的位置是两格之间求 min,我们只需要保证辅助的节点不被选上就可以,所以我们将其他的节点设为 +∞
  1. 填表顺序

    • 从下往上
    • 从右往左
  2. 返回值

    • 返回 dp[0][0]

代码编写

public int calculateMinimumHP(int[][] dungeon) {  
    //1. 创建 dp 表  
    int m = dungeon.length;  
    int n = dungeon[0].length;  
    int[][] dp = new int[m+1][n+1];  
  
    //2. 初始化  
    for (int j = 0; j <= n; j++)  
        dp[m][j] = Integer.MAX_VALUE;  
    for (int i = 0; i <= m; i++)  
        dp[i][n] = Integer.MAX_VALUE;  
  
    dp[m][n-1] = dp[m-1][n] = 1;  
  
    //3. 填表  
    for (int i = m-1; i >= 0; i--) {  
        for (int j = n-1; j >= 0; j--) {  
            dp[i][j] = Math.min(dp[i][j+1], dp[i+1][j]) - dungeon[i][j];  
            dp[i][j] = Math.max(dp[i][j], 1);  
        }  
    }  
    return dp[0][0];  
}

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

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

相关文章

leetcode_887_鸡蛋掉落___循序渐进的分析

分析&#xff1a;对于一组[n,k] 在一次尝试中选择了在dep层测试 其可以分为 如果在dep层炸了: 则变成了[dep-1,k-1]读作在dep-1层用k-1个鸡蛋来找鸡蛋的极限所需次数如果在dep层没炸: 则变成了[n-dep,k]读作在n-dep层用k个鸡蛋来找鸡蛋的极限所需次数可以发现这都是子问题的…

【Javaee】网络编程-TCP Socket

前言 前文中我们介绍了UDP Socket相关的构造方法和方法&#xff0c;并实现了UDP的回显服务器和客户端。 本篇将介绍TCP Socket&#xff0c;并使用TCP Socket api实现服务器和客户端的通信 一.TCP Socket的常见方法 1.ServerSocket ServerSocket是创建TCP服务端Socket的API …

线程池:高效管理并发任务的利器

线程池&#xff1a;高效管理并发任务的利器 什么是线程池&#xff1f; 线程池&#xff08;Thread Pool&#xff09;是Java并发编程中的一种设计模式&#xff0c;旨在通过重复利用线程资源&#xff0c;来提高程序执行效率。线程池的主要思想是提前创建一组可供使用的线程&#…

归一化输入

当输入的不同的特征取值范围差异过大&#xff0c;取得对应参数差别也会很大&#xff0c;在对参数进行优化的过程中&#xff0c;参数小的维度步长较小&#xff0c;参数大的维度步长较大&#xff0c;优化过程中路径曲折&#xff0c;将输入归一化&#xff0c;使特征取值范围差别小…

相控阵雷达电特性matlab模拟与仿真,带GUI界面,对比有限扫描阵,稀疏阵,多波束阵,共形阵等

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 相控阵雷达作为一种先进的雷达技术&#xff0c;具有高分辨率、多功能、快速扫描等优点&#xff0c;在军事和民用领域都有着广泛的应用。相控阵雷达的天线系统是其核心组成部分…

C#线性变换——缩放

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在C#开发中经常需要对平面中的坐标进行一些变换&#xff0c;比如缩放、旋转等&…

数据结构:二叉树、堆

目录 一.树的概念 二、二叉树 1.二叉树的概念 2.特殊类型的二叉树 3.二叉树的性质 4.二叉树存储的结构 三、堆 1.堆的概念 2.堆的实现 Heap.h Heap.c 一.树的概念 注意&#xff0c;树的同一层中不能有关联&#xff0c;否侧就不是树了&#xff0c;就变成图了&#xff…

PCL 点云配准 Trimed-ICP算法(精配准

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 perform_standard_icp 函数 2.1.2 perform_trimmed_icp 函数 2.1.3 visualize_registration 函数 2.2完整代码 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算…

国庆旅游高峰期,如何利用可视化报表来展现景区、游客及消费数据

国庆黄金周&#xff0c;作为国内旅游市场的年度盛宴&#xff0c;总是吸引着无数游客的目光。今年&#xff0c;随着旅游市场的强劲复苏&#xff0c;各大景区又再次迎来游客流量的高峰。全国国内出游7.65亿人次&#xff0c;同比增长5.9%&#xff0c;国内游客出游总花费7008.17亿元…

大型企业软件开发是什么样子的? - Web Dev Cody

引用自大型企业软件开发是什么样子的&#xff1f; - Web Dev Cody_哔哩哔哩_bilibili 一般来说 学技术的时候 我们会关注 开发语言特性 &#xff0c;各种高级语法糖&#xff0c;底层技术 但是很少有关注到企业里面的开发流程&#xff0c;本着以终为始&#xff08;以就业为导向…

界面控件Telerik UI for WPF 2024 Q3亮点 - 支持禁用数据过滤等

Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序&#xff0c;同时还能快速构建企业级办公WPF应用程序。UI for WPF支持MVVM、触摸等&#xff0c;创建的应用程序可靠且结构良好&#xff0c;非常容易维护&#xff0c;其直观的API将无缝地集成Visual Studio…

[Linux网络编程]03-TCP协议

一.TCP协议数据通信的过程 TCP数据报如下&#xff0c;数据报中的标志位双端通信的关键。 三次握手: 1.客户端向服务端发送SYN标志位&#xff0c;请求建立连接&#xff0c;同时发送空包 2.服务端向客户端回发ACK标志位(即确认标志位&#xff0c;任何一端发送数据后都需要另一端…

asyn驱动示例-int32driver

驱动程序源代码int32Driver.c&#xff1a; #include <stddef.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <ctype.h>#include <cantProceed.h> #include <epicsStdio.h> #i…

官龙村捐赠图书整理有感

今天&#xff08;2024年10月20日&#xff09;&#xff0c;我有幸参加了在深圳南山区西丽官龙村举行的义工活动&#xff0c;主要任务是整理捐赠的图书&#xff0c;并根据小学和中学的需求进行分类打包。这次活动不仅让我体会到了劳动的辛苦&#xff0c;更让我感受到了助人为乐的…

【AIGC】第一性原理下的ChatGPT提示词Prompt设计:系统信息与用户信息的深度融合

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;第一性原理与ChatGPT提示词Prompt设计应用第一性原理于ChatGPT提示词Prompt设计系统信息和用户信息的融合实际应用结论 &#x1f4af;系统信息与用户信息的定义和重要性系…

鸿蒙中富文本编辑与展示

富文本在鸿蒙系统如何展示和编辑的&#xff1f;在文章开头我们提出这个疑问&#xff0c;带着疑问来阅读这篇文章。 富文本用途可以展示图文混排的内容&#xff0c;在日常App 中非常常见&#xff0c;比如微博的发布与展示&#xff0c;朋友圈的发布与展示&#xff0c;都在使用富文…

C++高阶:红黑树实现

目录 一.红黑树的概念 1.1红黑树的规则 1.2红黑树的效率 二.红黑树的实现 2.1红黑树的结构 2.2红黑树的插入 2.2.1插入的大致过程 2.2.2情况一&#xff1a;变色 ​编辑 2.2.3情况二&#xff1a;单旋变色 2.2.4情况三&#xff1a;双旋变色 2.3插入代码实现 2.4红黑树的…

【网络安全】简单P1:通过开发者工具解锁专业版和企业版功能

未经许可,不得转载。 文章目录 前言发现过程前言 在探索一个SaaS平台的过程中,我发现了一个漏洞,使得我能够在无需订阅的情况下解锁高级(专业/企业)功能。 发现过程 我使用一个没有任何高级功能的基本用户账户进行常规登录。在浏览平台时,我注意到某些按钮和功能上带有…

【C++STL】list的基本介绍与使用方式

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山冈&#xff01; &#x1f525; 所属专栏&#xff1a;C深入学习笔记 &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 一、list的介绍 文档内容以及大致翻…

ROS笔记之kill掉所有ros节点rosnode

ROS笔记之kill掉所有ros节点rosnode 文章目录 ROS笔记之kill掉所有ros节点rosnode1. 杀死所有 ROS 节点&#xff08;不包括 rosmaster&#xff09;2. 杀死 rosmaster3. 验证所有节点和 rosmaster 是否已终止4. roscore 和 rosmaster 是同一个概念吗&#xff1f;5. 为什么执行 k…