LeetCode 2684. 矩阵中移动的最大次数

文章讲述了如何使用深度优先搜索和记忆化技术解决LeetCode上的矩阵移动问题,以及两种不同的解决方案:一种是在遍历过程中记录步数,另一种是计算每个节点可移动步数。两种方法都强调了不受已走过路径影响的特点。
摘要由CSDN通过智能技术生成

2684. 矩阵中移动的最大次数icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-number-of-moves-in-a-grid/description/?envType=daily-question&envId=2024-03-16这题刚看到想到的就是用深度优先遍历来做,结果超时了。仔细一看发现在移动单元格的时候永远都是向右的,也就是说不可能走到已经走过的单元格上。这说明每个子问题求解的时候不受前面已经走过的路径的影响。那么我们就可以给深度优先搜索加上一个备忘录,记录已经求解的子问题。此外甚至可以用动态规划来求解。

下面是带备忘录的递归(记忆化递归)的求解方法。

class Solution {
public:
    int current_steps=0;
    int max_steps=INT_MIN;
    int maxMoves(vector<vector<int>>& grid) {
        vector<vector<int>> mem(grid.size(), vector<int>(grid[0].size(), -1));
        for (int i=0; i < grid.size(); ++i) {
            dfs(grid, i, 0, INT_MIN, mem);
        }
        return max_steps - 1;
        
    }

    void dfs(vector<vector<int>>& grid, int x, int y, int pre, vector<vector<int>>& mem) {
        if (x < 0 || x == grid.size() || y < 0 || y == grid[0].size() ||grid[x][y] <= pre) {
            max_steps = max(current_steps, max_steps);
            return;
        }
        if (mem[x][y] != -1) {
            max_steps = max(max_steps, mem[x][y]);
            return ;
        }
        current_steps += 1;
        dfs(grid, x-1, y+1, grid[x][y], mem);
        dfs(grid, x, y+1, grid[x][y], mem);
        dfs(grid, x+1, y+1, grid[x][y], mem);
        current_steps -= 1;
        mem[x][y] = max_steps;
    }
};

 另外一种写法,跟上面的不同,上面的是深度优先遍历过程中记录已经走过的步数,并把经过当前点能达到的最大步数写在备忘录里。下面这种写法是记录从每个节点开始能移动多少步。两种写法代表两种不同的思路吧,但差别不大。

class Solution {
public:
    int maxMoves(vector<vector<int>>& grid) {
        vector<vector<int>> mem(grid.size(), vector<int>(grid[0].size(), -1));
        function<int(int, int)> dfs = [&] (int x, int y) -> int {
            if (mem[x][y] != -1) return mem[x][y];
            int res = 0;
            bool none_move = true;
            if (x - 1 >= 0 && y + 1 < grid[0].size() && grid[x-1][y+1] > grid[x][y]){
                res = max(res, dfs(x -1, y+1));
                none_move = false;
            }
            if (y + 1 < grid[0].size() && grid[x][y+1] > grid[x][y]) {
                res = max(res, dfs(x, y+1));
                none_move = false;
            }
            if (x + 1 < grid.size() && y + 1 < grid[0].size() && grid[x+1][y+1] > grid[x][y]) {
                res = max(res, dfs(x + 1, y + 1));
                none_move = false;
            }
            if (none_move) {
                mem[x][y] = 0;
                return 0;
            }
            mem[x][y] = res + 1;
            return mem[x][y];
        };
        int result = 0;
        for (int i=0; i < grid.size(); ++i) {
            result = max(dfs(i, 0), result);
        }
        return result;
        
    }


};

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值