LeetCode432周赛T2,记忆化搜刮

打印 上一主题 下一主题

主题 856|帖子 856|积分 2568

3418. 机器人可以得到的最大金币数
给你一个 m x n 的网格。一个机器人从网格的左上角(0, 0)出发,目标是到达网格的右下角 (m - 1, n - 1)。在恣意时刻,机器人只能向右或向下移动。
网格中的每个单位格包含一个值 coins[j]:
如果 coins[j] >= 0,机器人可以得到该单位格的金币。
如果 coins[j] < 0,机器人会遇到一个强盗,强盗会抢走该单位格数值的 绝对值 的金币。
机器人有一项特殊能力,可以在行程中 最多感化 2个单位格的强盗,从而防止这些单位格的金币被抢走。
注意:机器人的总金币数可以是负数。
返回机器人在路径上可以得到的 最大金币数 。
  1. 示例 1:
  2. 输入: coins = [[0,1,-1],[1,-2,3],[2,-3,4]]
  3. 输出: 8
  4. 解释:
  5. 一个获得最多金币的最优路径如下:
  6. 从 (0, 0) 出发,初始金币为 0(总金币 = 0)。
  7. 移动到 (0, 1),获得 1 枚金币(总金币 = 0 + 1 = 1)。
  8. 移动到 (1, 1),遇到强盗抢走 2 枚金币。机器人在此处使用一次感化能力,避免被抢(总金币 = 1)。
  9. 移动到 (1, 2),获得 3 枚金币(总金币 = 1 + 3 = 4)。
  10. 移动到 (2, 2),获得 4 枚金币(总金币 = 4 + 4 = 8)。
  11. 示例 2:
  12. 输入: coins = [[10,10,10],[10,10,10]]
  13. 输出: 40
  14. 解释:
  15. 一个获得最多金币的最优路径如下:
  16. 从 (0, 0) 出发,初始金币为 10(总金币 = 10)。
  17. 移动到 (0, 1),获得 10 枚金币(总金币 = 10 + 10 = 20)。
  18. 移动到 (0, 2),再获得 10 枚金币(总金币 = 20 + 10 = 30)。
  19. 移动到 (1, 2),获得 10 枚金币(总金币 = 30 + 10 = 40)。
  20. 提示:
  21. m == coins.length
  22. n == coins[i].length
  23. 1 <= m, n <= 500
  24. -1000 <= coins[i][j] <= 1000
复制代码
本题是三个状态的记忆化搜刮,但感觉dp不符合直觉,所以用记忆化搜刮来做
dfs(i,j,k)从当前这个位置(i,j)出发到达左上角(0,0)切最多感化强盗k次的最值
搜刮的思绪一般比较固定,对于记忆化搜刮的题目,肯定都是有返回值的.,而且,参数里有坐标。
第一步,判定当前点是否有意义,即判定是否越界。
if (i < 0 || j < 0) return INF;
第二步,是否到达目标点,如果到达左上角了,记得特判一下是否还有时机感化大概直接返回
  1. int x = coins[i][j];
  2. // 到达左上角位置
  3. if(i == 0 && j == 0)return k > 0 ? max(0,x);
复制代码
第三步,拿到记忆化的值,判定是否已经走过
  1. int &res = memo[i][j][k];
  2. if( res != INF)return memo[i][j][k];
复制代码
第四步,走到下一步,而且更新当前最大值
  1. res = max({res, dfs(i, j - 1, k) + x, dfs(i - 1, j, k) + x});
  2. if(x  < 0 && k > 0) res = max({res,dfs(i, j - 1, k - 1), dfs(i - 1, j, k -1)});
复制代码
第五步,返回当前dfs的寄义
  1. return res;
复制代码
由于本题负数最大为2.5* 1e8,所以memo的初始化要思量到不能爆int,初始化为-0x3f3f3f3f,大约为-1e9.
完整代码
  1. class Solution {public:    const int INF = -0x3f3f3f3f;    int maximumAmount(vector<vector<int>>& coins) {        int n = coins.size(), m = coins[0].size();        vector memo(n,vector(m , vector<int>(3, INF)));        function<int(int,int,int)> dfs = [&](int i, int j, int k){             // 处理界限情况            if (i < 0 || j < 0) return INF;                       int x = coins[i][j];            // 到达左上角位置            if(i == 0 && j == 0)return k > 0 ? max(0,x) : x;            int &res = memo[i][j][k];            if( res != INF)return memo[i][j][k];            res = max({res, dfs(i, j - 1, k) + x, dfs(i - 1, j, k) + x});            if(x  < 0 && k > 0) res = max({res,dfs(i, j - 1, k - 1), dfs(i - 1, j, k -1)});            return res;
  2.         };        return dfs(n-1,m-1,2);    }};
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表