Problem of The Day: Find Minimum Time to Reach Last Room II
Problem Statement
Intuition
The problem is to determine the minimum time required to reach the bottom-right cell of a 2D grid, given certain movement costs and conditions that alternate at each step. The idea is to use a shortest path algorithm (like Dijkstra’s) that adapts to the grid constraints and alternating movement costs.
Approach
We model this as a shortest-path problem on a grid, where each cell has a time cost constraint (moveTime[row][col]) that affects the next move. The movement alternates between fast and slow (1 unit vs. 2 units) depending on a boolean alternate flag, which flips every move. We use a min-heap (priority queue) to always expand the node with the least accumulated time.
- Initialize a distancematrix to store the minimum time to reach each cell.
- Use a min-heap starting from the top-left cell (0,0)with time0andalternate=True.
- For each cell, explore all 4 directions (up, down, left, right).
- If the current time is less than the time constraint moveTime[r][c], wait until that time.
- Update the time based on whether it is an alternate (1 unit) or not (2 units) step.
- If this new time is better than the recorded time in distance, update and push to the heap.
Complexity
- 
    Time complexity: 
 \(O(R \cdot C \cdot \log(R \cdot C))\)
 where ( R ) is the number of rows and ( C ) is the number of columns. Each cell may be processed once in the priority queue.
- 
    Space complexity: 
 \(O(R \cdot C)\)
 for thedistance,visited, and heap storage.
Code
class Solution:
    def minTimeToReach(self, moveTime: List[List[int]]) -> int:
        ROWS = len(moveTime)
        COLS = len(moveTime[0])
        distance = [[float('inf') for _ in range(COLS)] for _ in range(ROWS)]
        visited = [[False for _ in range(COLS)] for _ in range(ROWS)]
        min_heap = [[0, 0, 0, True]]
        distance[0][0] = 0
        while min_heap:
            time, row, col, alternate = heapq.heappop(min_heap)
            for x, y in [(0,1),(1,0),(-1,0),(0,-1)]:
                next_row = row + x
                next_col = col + y
                if 0 <= next_row < ROWS and 0 <= next_col < COLS and not visited[next_row][next_col]:
                    d = 0
                    if time < moveTime[next_row][next_col]:
                        d = moveTime[next_row][next_col] + (1 if alternate else 2)
                    else:
                        d = time + (1 if alternate else 2)
                    if d < distance[next_row][next_col]:
                        distance[next_row][next_col] = d
                        heapq.heappush(min_heap, [d, next_row, next_col, not alternate])
                    visited[next_row][next_col] = True
        return distance[-1][-1]
Editorial
Approach: Shortest Path + Dijkstra
class State:
    def __init__(self, x, y, dis):
        self.x = x
        self.y = y
        self.dis = dis
    def __lt__(self, other):
        return self.dis < other.dis
class Solution:
    def minTimeToReach(self, moveTime):
        n = len(moveTime)
        m = len(moveTime[0])
        inf = float("inf")
        d = [[inf] * m for _ in range(n)]
        v = [[0] * m for _ in range(n)]
        dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]
        d[0][0] = 0
        q = []
        heapq.heappush(q, State(0, 0, 0))
        while q:
            s = heapq.heappop(q)
            if v[s.x][s.y]:
                continue
            if s.x == n - 1 and s.y == m - 1:
                break
            v[s.x][s.y] = 1
            for dx, dy in dirs:
                nx, ny = s.x + dx, s.y + dy
                if not (0 <= nx < n and 0 <= ny < m):
                    continue
                dist = max(d[s.x][s.y], moveTime[nx][ny]) + (s.x + s.y) % 2 + 1
                if d[nx][ny] > dist:
                    d[nx][ny] = dist
                    heapq.heappush(q, State(nx, ny, dist))
        return d[n - 1][m - 1]