The Indian Engineer

Problem 3286 Find a Safe Walk Through a Grid

Posted on 4 mins

Queue Bfs Matrix Dp Dynamic-Programming

Problem Statement

Link - Problem 3286

Question

You are given an m x n binary matrix grid and an integer health.

You start on the upper-left corner (0, 0) and would like to get to the lower-right corner (m - 1, n - 1). You can move up, down, left, or right from one cell to another adjacent cell as long as your health remains positive.

Return true if you can reach the final cell with a health value of 1 or more, and false otherwise.

Example 1

Input: grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]], health = 1

Output: true

Explanation:
The final cell can be reached safely by walking along the gray cells below.

img1

Example 2

Input: grid = [[0,1,1,0,0,0],[1,0,1,0,0,0],[0,1,1,1,0,1],[0,0,1,0,1,0]], health = 3

Output: false

Explanation:
A minimum of 4 health points is needed to reach the final cell safely.

img2

Example 3

Input: grid = [[1,1,1],[1,0,1],[1,1,1]], health = 5

Output: true

Explanation:
The final cell can be reached safely by walking along the gray cells below.
Any path that does not go through the cell (1, 1) is unsafe
since your health will drop to 0 when reaching the final cell.

img3

Constraints

Solution

class Solution {
public:
    bool findSafeWalk(vector<vector<int>>& grid, int health) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m, vector<int>(n, -1));
        dp[0][0] = health - grid[0][0];

        queue<pair<int, int>> q;
        q.push({0, 0});

        vector<int> dirX = {1, -1, 0, 0};
        vector<int> dirY = {0, 0, 1, -1};

        while (!q.empty()) {
            auto [x, y] = q.front();
            q.pop();

            for (int i = 0; i < 4; ++i) {
                int newX = x + dirX[i], newY = y + dirY[i];
                if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
                    int nheal = dp[x][y] - grid[newX][newY];
                    if (nheal > dp[newX][newY]) {
                        dp[newX][newY] = nheal;
                        if (nheal > 0) {
                            q.push({newX, newY});
                        }
                    }
                }
            }
        }
       // for(int i=0;i<m;i++){
         //   for(int j = 0; j<n ; j++){
           //       cout<<dp[i][j]<<" ";
            //}
            //cout<<endl;
        //}
        return dp[m-1][n-1] > 0;
    }
};

Complexity Analysis

| Algorithm | Time Complexity | Space Complexity |
| --------- | --------------- | ---------------- |
| BFS       | O(mn)           | O(mn)            |

Explanation

1. Intuition

2. Implementation

- Initialize a 2D vector `dp` of size `m x n` with -1.
- Set the health at the starting cell to `health - grid[0][0]`.
- Initialize a queue `q` to store the cells to be traversed.
- Push the starting cell (0, 0) to the queue.
- Initialize two vectors `dirX` and `dirY` to store the directions.
- While queue is not empty,
  - Pop the front cell from the queue.
  - For each direction, if the cell is valid
    - Calculate the health at the adjacent cell as `dp[x][y] - grid[newX][newY]`.
    - If the health at the adjacent cell is greater than the health in dp array, update the health in dp array.
    - If the health at the adjacent cell is greater than 0, push the cell to the queue.
- Return the health at the end cell and check if it is greater than 0.