首页 > 其他分享 >【动态规划】矩阵

【动态规划】矩阵

时间:2024-01-24 16:25:47浏览次数:36  
标签:int 矩阵 grid 2.2 2.1 动态 规划 骑士 dp

目录

1. 题目列表

序号 题目 难度
1 64. 最小路径和 中等
2 174. 地下城游戏 困难

2. 应用

2.1. Leetcode 64. 最小路径和

2.1.1. 题目

64. 最小路径和

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。说明:每次只能向下或者向右移动一步。

示例 1:

image
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。

2.1.2. 分析

这里,我们使用动态规划的思路求解,我们假设 \(dp[i][j]\) 表示到达位置 \((i, j)\) 的最小路径和,同时,假设 \(m\) 和 \(n\) 分别表示矩阵的高和宽。

2.1.2.1. 边界条件

当矩阵的大小为 \(1\) 时,那么,最小的路径,就是当前网格中的数值,即

\[dp[0][0] = grid[0][0] \]

当矩阵只有一列时,最小路径和,就是这一列的数值之和,即

\[dp[i][0] = dp[i - 1][0] + grid[i][0], i \ge 1 \]

当矩阵只有一行时,最小路径和,就是这一行的数值之和,即

\[dp[0][j] = dp[0][j - 1] + grid[0][j], j \ge 1 \]

2.1.2.2. 状态转移

我们容易看出来,当 \(1 \le i < n\) 且 \(1 \le j < n\) 时,在矩阵中的任意一个位置,都有

\[dp[i][j] = \min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j],\quad 1 \le i < n, 1 \le j < n \]

2.1.3. 代码实现

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int [][] dp = new int[m][n];

        dp[0][0] = grid[0][0];
        for (int i = 1; i < m; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }

        for (int j = 1; j < n; j++) {
            dp[0][j] = dp[0][j - 1] + grid[0][j];
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
            }
        }
        return dp[m - 1][n - 1];
    }
}

2.2. Leetcode 174. 地下城游戏

2.2.1. 题目

174. 地下城游戏

恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若 房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快解救公主,骑士决定每次只 向右向下 移动一步。
返回确保骑士能够拯救到公主所需的最低初始健康点数。
注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

示例 1:

image

输入:dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
输出:7
解释:如果骑士遵循最佳路径:右 -> 右 -> 下 -> 下 ,则骑士的初始健康点数至少为 7 。

2.2.2. 分析

题目中要求骑士的血量等于或小于 \(0\) 就会死亡,也就是说,在每一个位置,骑士最少的血量至少为 \(1\)。

我们可以考虑,从终点逆向返回起点,如果它,计算每一个位置会消耗的血量,就可以得到起始位置骑士的初始血量了。

假设 \(dp[i][j]\) 表示骑士从位置 \((i, j)\) 出发,到达位置终点所需要消耗的最少血量,同时,假设 \(m\) 和 \(n\) 分别表示矩阵的高和宽。

2.2.2.1. 初始条件

显然,如果骑士只走一步到达终点,那么,他可以从位置 \((m, n - 1)\) 或者 \((m - 1, n)\) 出发,他需要的最少血量为 \(1\),因此,有

\[\begin{aligned} dp[m][n - 1] = 1 \\ dp[m - 1][n] = 1 \end{aligned} \]

2.2.2.2. 状态转移

我们从某一个位置 \((i, j)\) 前进时,骑士只能向左或者向下两个方向可以移动,即下一个位置只能是 \((i + 1, j)\) 或者 \((i, j + 1)\),这里,只需要关注从这两个位置到达终点的最小血量即可。

也就是说,我们在位置 \((i, j)\) 的初始血量只需要达到 \(min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]\) 即可。

同时,我们还需要保证每一个位置的最少血量大于等于 \(1\),因此,当前位置需要的最少血量就是:

\[dp[i][j] = max(min(dp[i + 1][j], \ dp[i][j + 1]) - dungeon[i][j], 1), 0 \le i \le m - 1, 0 \le j \le n - 1 \]

2.2.3. 代码实现

class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        int m = dungeon.length, n = dungeon[0].length;
        int [][] dp = new int [m + 1][n + 1];

        for(int [] row : dp) {
            Arrays.fill(row, Integer.MAX_VALUE);
        }

        dp[m][n - 1] = 1;
        dp[m - 1][n] = 1;
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                dp[i][j] = Math.max(Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j], 1);
            }
        }
        return dp[0][0];
    }
}

标签:int,矩阵,grid,2.2,2.1,动态,规划,骑士,dp
From: https://www.cnblogs.com/larry1024/p/17984317

相关文章

  • Vue 动态加载本地图片 404 的问题
    今天在vue文件中动态引入本地图片时发现路径没有问题但是一直404template部分如下,使用v-for动态加载,数据存储在setup中的nearbyItems数组内<template><divclass="nearby"><divclass="title">附近店铺</div><divv-for="iteminnear......
  • MarkDown基础及表格、KaTeX公式、矩阵、流程图、UML图、甘特图语法
    概述最多可设置6级标题技巧列表有序列表MD语法:1.你好2.我也好呈现效果:你好我也好无序列表MD语法:-a-b*aa*bb+aaa+bbb效果:abaabbaaabbb结论,支持三种方式:-、*、+TODO列表MD语法:-[x]后端接口开发-[]与前端联调呈现效果:后端......
  • UniApp Vue3 动态表单
    左侧手机部分为动态表单内容,右侧为提交后获取到表单的值。页面代码:<viewstyle="margin:15px;padding:10rpx;"><tn-formlabel-position="top"ref="formRef":model="formData":rules="formRules"><tn-for......
  • 静态区间查询(条件动态)——ST表
    目录问题引入思路一览具体分析条件动态?问题引入给出一个长度为n的数组a,并且给出m咨询问,每次询问给出边间lt和rt,要求给出lt和rt之间的最大值思路一览暴力法:记录数组,对于每一次询问,就从lt到rt遍历一遍ST:对数组的区间做一个倍增处理,将每一个区间的答案记录下来,最后使用区间进行......
  • 2024-01-24:用go语言,已知一个n*n的01矩阵, 只能通过通过行交换、或者列交换的方式调整矩
    2024-01-24:用go语言,已知一个n*n的01矩阵,只能通过通过行交换、或者列交换的方式调整矩阵,判断这个矩阵的对角线是否能全为1,如果能返回true,不能返回false。我们升级一下:已知一个n*n的01矩阵,只能通过通过行交换、或者列交换的方式调整矩阵,判断这个矩阵的对角线是否能全为1,如果......
  • router4j--SpringCloud动态路由利器
    前言本文介绍Java的动态路由中间件:router4j。router4j用于SpringCloud项目,它可以将某个url请求路由到指定的机器上,也可以将所有请求强制转到指定机器。问题描述Java后端在开发SpringCloud项目时如果同一个应用起了多个实例,会遇到以下问题:无法将指定url请求强制转到个人电脑。这样会......
  • Linux-unbuntu里静态库、动态库
    静态库:特点:生成的可执行程序复制了一份整个库,以空间换取时间第一步:准备功能函数eg:add.c sub.c  div.c...第二步:把功能函数只编译不链接,得到.o文件gcc-cadd.c-oadd.o第三步:将功能函数的.o文件进行打包成库(打包完成会生成一个.a结尾的库,此库里已经把功能函数都封装进来了)ar......
  • Mygin实现动态路由
    本篇是Mygin的第四篇目的使用Trie树实现动态路由解析。参数绑定前缀树本篇比前几篇要复杂一点,原来的路由是用map实现,索引非常高效,但是有一个弊端,键值对的存储的方式,只能用来索引静态路由。遇到类似hello/:name这动态路由就无能为力了,实现动态路由最常用的数据结构,被称为......
  • 编辑距离 动态规划又一题型
    这种题目一般是给两个字符串,找一些特性或进行一些操作。根据题目意思设置二维数组,行列长度为两个字数组的长度加1。之所以加一是为了留空间对空字符串进行讨论。递推式就是两个数组中如果元素相等怎么样,不相等又怎么样。最长公共子序列:点击查看代码if(text1[i-1]==text......
  • 动态 DP
    序列——线段树维护矩阵转移首先,我们需要普通DP方程改为矩阵乘法或广义矩阵乘法形式,可能会增加一些状态,然后用线段树维护矩阵乘法即可。这个模型推荐使用横向量乘方阵的形式,可以直接从左往右乘。树——重链剖分原理首先,记录每个节点的轻儿子对这个节点DP数组的贡献,然后用......