Graph + Matrix solution [EXPLAINED]
IntuitionFind the shortest time to reach the bottom-right corner of the grid, considering the conditions of when I need to wait based on the values in each cell
# Intuition
Find the shortest time to reach the bottom-right corner of the grid, considering the conditions of when I need to wait based on the values in each cell. The challenge is to account for both the time spent moving and waiting, ensuring that I can find the most efficient path.

# Approach
I’ll use a priority queue to always process the cell with the smallest time first, moving in all four directions (up, right, down, left), updating the time as I go. I’ll also mark visited cells to avoid reprocessing and account for waiting times when necessary by adjusting the time if the current cell requires more time to proceed.

# Complexity
- Time complexity:
𝑂((𝑁 × 𝑀) log ⁡(𝑁 × 𝑀)), where 𝑁 is the number of rows and 𝑀 is the number of columns. This is because we use a priority queue, and each cell can be pushed and popped from the queue once.

- Space complexity:
O(N×M), which is used to store the seen array and the priority queue, both of which store up to N × M elements in the worst case.

# Code
```rust []
use std::cmp::Reverse;
use std::collections::BinaryHeap;

const MOVES: [[i32; 2]; 4] = [[-1, 0], [0, 1], [1, 0], [0, -1]]; // Possible moves (up, right, down, left)

impl Solution {
    pub fn minimum_time(grid: Vec<Vec<i32>>) -> i32 {
        let rows = grid.len(); // Get the number of rows in the grid
        let cols = grid[0].len(); // Get the number of columns in the grid
        
        // If the top-right or bottom-left corners have a non-zero value greater than 1, it's impossible to proceed
        if grid[0][1] > 1 && grid[1][0] > 1 {
            return -1;
        }
        
        let mut pq = BinaryHeap::new(); // BinaryHeap is a max-heap, so we reverse values to simulate a min-heap
        let mut seen = vec![vec![false; cols]; rows]; // 2D array to track visited cells
        
        // Start from the top-left corner (0, 0) with a time of 0
        pq.push(Reverse((0, 0, 0))); // (time, row, col)
        seen[0][0] = true; // Mark the starting cell as visited
        
        // Start processing the cells in the priority queue
        while let Some(Reverse(curr)) = pq.pop() {
            let (time, row, col) = curr; // Get the current time, row, and column from the queue
            
            // Try moving in all four directions
            for dir in MOVES.iter() {
                let new_row = row as i32 + dir[0]; // Calculate the new row position
                let new_col = col as i32 + dir[1]; // Calculate the new column position
                
                // Skip if out of bounds or already visited
                if new_row < 0 || new_row >= rows as i32 || new_col < 0 || new_col >= cols as i32 || seen[new_row as usize][new_col as usize] {
                    continue;
                }
                
                // Calculate the new time (move to the next cell)
                let mut new_time = time + 1;
                
                // If the cell requires waiting, calculate how long to wait
                if grid[new_row as usize][new_col as usize] > new_time {
                    let wait = ((grid[new_row as usize][new_col as usize] - new_time + 1) / 2) * 2; // Wait for the right time
                    new_time += wait; // Increment the time by the wait time
                }
                
                // If we reached the bottom-right corner, return the time
                if new_row == (rows - 1) as i32 && new_col == (cols - 1) as i32 {
                    return new_time;
                }
                
                // Mark the new cell as visited
                seen[new_row as usize][new_col as usize] = true;
                
                // Push the new time and position to the priority queue
                pq.push(Reverse((new_time, new_row as usize, new_col as usize)));
            }
        }
        
        // If no valid path to the bottom-right corner, return -1
        -1
    }
}

```
['Array', 'Breadth-First Search', 'Graph', 'Heap (Priority Queue)', 'Matrix', 'Shortest Path', 'Rust']