【LetMeFly】3418.机器人可以获得的最大金币数:动态规划
力扣题目链接:https://leetcode.cn/problems/maximum-amount-of-money-robot-can-earn/
给你一个 m x n 的网格。一个机器人从网格的左上角 (0, 0) 出发,目标是到达网格的右下角 (m - 1, n - 1)。在任意时刻,机器人只能向右或向下移动。
网格中的每个单元格包含一个值 coins[i][j]:
- 如果
coins[i][j] >= 0,机器人可以获得该单元格的金币。 - 如果
coins[i][j] < 0,机器人会遇到一个强盗,强盗会抢走该单元格数值的 绝对值 的金币。
机器人有一项特殊能力,可以在行程中 最多感化2个单元格的强盗,从而防止这些单元格的金币被抢走。
**注意:**机器人的总金币数可以是负数。
返回机器人在路径上可以获得的 最大金币数。
示例 1:
输入: coins = [[0,1,-1],[1,-2,3],[2,-3,4]]
输出: 8
解释:
一个获得最多金币的最优路径如下:
- 从
(0, 0)出发,初始金币为0(总金币 =0)。 - 移动到
(0, 1),获得1枚金币(总金币 =0 + 1 = 1)。 - 移动到
(1, 1),遇到强盗抢走2枚金币。机器人在此处使用一次感化能力,避免被抢(总金币 =1)。 - 移动到
(1, 2),获得3枚金币(总金币 =1 + 3 = 4)。 - 移动到
(2, 2),获得4枚金币(总金币 =4 + 4 = 8)。
示例 2:
输入: coins = [[10,10,10],[10,10,10]]
输出: 40
解释:
一个获得最多金币的最优路径如下:
- 从
(0, 0)出发,初始金币为10(总金币 =10)。 - 移动到
(0, 1),获得10枚金币(总金币 =10 + 10 = 20)。 - 移动到
(0, 2),再获得10枚金币(总金币 =20 + 10 = 30)。 - 移动到
(1, 2),获得10枚金币(总金币 =30 + 10 = 40)。
提示:
m == coins.lengthn == coins[i].length1 <= m, n <= 500-1000 <= coins[i][j] <= 1000
解题方法:动态规划
令 d p [ t h ] [ i ] [ j ] dp[th][i][j] dp[th][i][j]代表到达 ( i , j ) (i, j) (i,j)时感化强盗最多 t h th th次的最大收益。
- 如果不感化: d p [ t h ] [ i ] [ j ] = c o i n s [ i ] [ j ] + max ( d p [ t h ] [ i − 1 ] [ j ] , d p [ t h ] [ i ] [ j − 1 ] ) dp[th][i][j]=coins[i][j] + \max(dp[th][i-1][j], dp[th][i][j-1]) dp[th][i][j]=coins[i][j]+max(dp[th][i−1][j],dp[th][i][j−1])(上左最大的那个 + 本格子)
- 如果感化: d p [ t h ] [ i ] [ j ] = max ( d p [ t h − 1 ] [ i − 1 ] [ j ] , d p [ t h − 1 ] [ i ] [ j − 1 ] ) dp[th][i][j] = \max(dp[th-1][i-1][j], dp[th-1][i][j-1]) dp[th][i][j]=max(dp[th−1][i−1][j],dp[th−1][i][j−1]) (上左 t h − 1 th-1 th−1次感化中最大的那个)
注意判断下边界条件 t h th th、 i i i、 j j j大于或等于 0 0 0就好。
- 时间复杂度 O ( n m ) O(nm) O(nm)
- 空间复杂度 O ( n m ) O(nm) O(nm)
AC代码
C++
cpp
/*
* @LastEditTime: 2026-04-03 08:29:08
*/
const int INF = 1e9;
class Solution {
public:
int maximumAmount(vector<vector<int>>& coins) {
int n = coins.size(), m = coins[0].size();
array<vector<vector<int>>, 3> dp;
dp.fill(vector<vector<int>>(n, vector<int>(m)));
dp[0][0][0] = coins[0][0];
dp[1][0][0] = dp[2][0][0] = max(coins[0][0], 0);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (!i && !j) {
continue;
}
for (int th = 0; th < 3; th++) {
dp[th][i][j] = coins[i][j] + max(i ? dp[th][i - 1][j] : -INF, j ? dp[th][i][j - 1] : -INF);
}
for (int th = 1; th < 3; th++) {
dp[th][i][j] = max(dp[th][i][j], max(i ? dp[th - 1][i - 1][j] : -INF, j ? dp[th - 1][i][j - 1] : -INF));
}
}
}
return dp[2][n - 1][m - 1];
}
};
空间优化
TODO:
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源