3286、穿越网格图的安全路径

3286、[中等] 穿越网格图的安全路径

1、题目描述

给你一个 m x n 的二进制矩形 grid 和一个整数 health 表示你的健康值。你开始于矩形的左上角 (0, 0) ,你的目标是矩形的右下角 (m - 1, n - 1) 。你可以在矩形中往上下左右相邻格子移动,但前提是你的健康值始终是 正数

对于格子 (i, j) ,如果 grid[i][j] = 1 ,那么这个格子视为 不安全 的,会使你的健康值减少 1 。如果你可以到达最终的格子,请你返回 true ,否则返回 false

注意 ,当你在最终格子的时候,你的健康值也必须为 正数

2、解题思路

这个问题可以通过图的最短路径算法来解决。我们需要使用一个动态规划 (DP) 方法来记录从起点到每个位置所需的最小健康值。在这个问题中,我们可以将 DP 结合 DFS 来实现。

详细步骤

  1. 初始化
    • 创建一个二维 DP 数组 dp,用于记录从起点 (0, 0) 到每个位置 (i, j) 所需的最小健康值。
    • 将 DP 数组初始化为 INT_MAX(一个非常大的数),表示未访问的状态。起点 (0, 0) 的 DP 值初始化为 grid[0][0],即起点的健康消耗值。
  2. DFS 遍历
    • 使用 DFS 遍历矩阵中的每个位置 (i, j)
    • 对于每个位置 (i, j),尝试向四个方向移动,检查是否可以到达邻居格子,并更新其 DP 值。
    • 如果到达新位置的最小健康值小于当前已知值,则更新 DP 值,并继续从该位置进行 DFS 遍历。
  3. 结束条件
    • 最后检查 DP 数组中终点 (m-1, n-1) 的值是否小于初始健康值 health。如果是,则表示可以在健康值大于 0 的情况下到达终点。

3、代码实现

#include <vector>
#include <limits.h>

using namespace std;

class Solution {
private:
    int pos[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 上、下、左、右方向

public:
    bool findSafeWalk(vector<vector<int>>& grid, int health) {
        int row = grid.size();
        int col = grid[0].size();
        vector<vector<int>> dp(row, vector<int>(col, INT_MAX));
        dp[0][0] = grid[0][0]; // 起点的健康消耗

        dfs(grid, dp, row, col, 0, 0); // 从起点开始进行 DFS

        return dp[row - 1][col - 1] < health; // 检查终点的最小健康值
    }

    void dfs(vector<vector<int>>& grid, vector<vector<int>>& dp, int row, int col, int i, int j) {
        for (int k = 0; k < 4; k++) { // 四个方向
            int x = i + pos[k][0];
            int y = j + pos[k][1];

            if (x >= 0 && x < row && y >= 0 && y < col) { // 检查边界
                if (dp[x][y] > dp[i][j] + grid[x][y]) { // 更新 DP 值
                    dp[x][y] = dp[i][j] + grid[x][y];
                    dfs(grid, dp, row, col, x, y); // 继续 DFS
                }
            }
        }
    }
};

这个解法结合了 DFS 和动态规划,通过在矩阵中维护最小健康值来确保从起点到终点的路径在健康值条件下是可行的。

相关推荐
网易独家音乐人Mike Zhou2 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
‘’林花谢了春红‘’4 小时前
C++ list (链表)容器
c++·链表·list
机器视觉知识推荐、就业指导5 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
Swift社区6 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
Kent_J_Truman7 小时前
greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用
算法
IT 青年7 小时前
数据结构 (1)基本概念和术语
数据结构·算法
Yang.997 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王7 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_7 小时前
C++自己写类 和 运算符重载函数
c++