3651.带传送的最小路径成本:动态规划
【LetMeFly】3651.带传送的最小路径成本:动态规划
力扣题目链接:https://leetcode.cn/problems/minimum-cost-path-with-teleportations/
给你一个 m x n 的二维整数数组 grid 和一个整数 k。你从左上角的单元格 (0, 0) 出发,目标是到达右下角的单元格 (m - 1, n - 1)。
有两种移动方式可用:
-
普通移动:你可以从当前单元格
(i, j)向右或向下移动,即移动到(i, j + 1)(右)或(i + 1, j)(下)。成本为目标单元格的值。 -
传送:你可以从任意单元格
(i, j)传送到任意满足grid[x][y] <= grid[i][j]的单元格(x, y);此移动的成本为 0。你最多可以传送k次。
返回从 (0, 0) 到达单元格 (m - 1, n - 1) 的 最小 总成本。
示例 1:
输入: grid = [[1,3,3],[2,5,4],[4,3,5]], k = 2
输出: 7
解释:
我们最初在 (0, 0),成本为 0。
| 当前位置 | 移动 | 新位置 | 总成本 |
|---|---|---|---|
(0, 0) |
向下移动 | (1, 0) |
0 + 2 = 2 |
(1, 0) |
向右移动 | (1, 1) |
2 + 5 = 7 |
(1, 1) |
传送到 (2, 2) |
(2, 2) |
7 + 0 = 7 |
到达右下角单元格的最小成本是 7。
示例 2:
输入: grid = [[1,2],[2,3],[3,4]], k = 1
输出: 9
解释:
我们最初在 (0, 0),成本为 0。
| 当前位置 | 移动 | 新位置 | 总成本 |
|---|---|---|---|
(0, 0) |
向下移动 | (1, 0) |
0 + 2 = 2 |
(1, 0) |
向右移动 | (1, 1) |
2 + 3 = 5 |
(1, 1) |
向下移动 | (2, 1) |
5 + 4 = 9 |
到达右下角单元格的最小成本是 9。
提示:
2 <= m, n <= 80m == grid.lengthn == grid[i].length0 <= grid[i][j] <= 1040 <= k <= 10
解题方法:动态规划
假设这道题不能跳跃,那么就变成了一个简答的二维DP:
1 | |
加上了个跳跃:高处往低处(或等高处)跳跃不增加cost,也就是说假设高处有个位置的到达代价是$a$,那么全图任何不高于它的位置都能以代价$a$到达。
所以我们可以在动态规划函数上添加一维,$dp[k][i][j]$表示进行$k$次跳跃到达$grid[i][j]$的最小代价。
所以,我们在最外层循环增加$k$次跳跃就好啦!对于第$times$次跳跃:
由高到低遍历grid
假设6个单元格高度分别是$[2, 2, 1, 1, 1, 0]$,那么先遍历height为$2$的两个单元格,并更新height为$2$的单元格的最小cost为其中最小的那个;
接着遍历height为$1$的三个单元格,并更新$height$为$1$的单元格的最小cost为这$5$个单元格中最小的那个。
具体做法:使用一个变量$miniFrom$记录当前所有高度的最小值,使用一个哈希表记录每一高度下都有哪些格子,由高到低一层一层地遍历,更新$miniFrom$后再遍历一遍这一层。
每层先由$times-1$的那个dp跳跃而来,然后再执行一遍正常的二维DP(normalRightDownDP)就好了。
由于可以零成本原地跳到原地,所以最终返回跳完所有$k$次的那个DP的右下角格子就好了。
- 时间复杂度$O(mnk)$
- 空间复杂度$O(mnk)$
AC代码
C++
1 | |
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源