I hope you like it
Let's say, I am just proud of myself 😅.First, note that if we can take the first move, we can reach the last cell too, as we can move back and fourth between th

Let's say, I am just proud of myself 😅. 

First, note that if we can take the first move, we can reach the last cell too, as we can move back and fourth between the first two cells till all the cells are open to enter.

Moreover, assuming a cell is reachable via a path of valid cells (including the target as well), we can be at that cell only if `(time + row + col) % 2 == 0`, where row and cell denote the location of cell. By this, I mean for any `cell = (row, col)`, if `(row + col) % 2 == 0`, then we can be there only if `time % 2 == 0`. 

In the following code, we iterate over the time, and keep track of all the cells that are adjecent to the cells we have visited so far. At each time, if the timer is even, this means that we can be visiting a new valid even cell which was adjecent to our visited cells, and move to an odd cell. So we pop from even current adjecnt cells, and push new odd adjacents to the odd heap.

# Complexity
- Time complexity:
Note that it is possible to push all the cells in the heap, and pop all of them. This task is equivalent to sorting, which takes $n\log n$, where $n$ is the number of elements. So, the time complexity of this algorithm is:
$O(mn\log(mn))$ 
- Space complexity:
$O(mn)$

# Code
```python3 []
import heapq
class Solution:
    def minimumTime(self, grid: List[List[int]]) -> int:
        if grid[0][1] > 1 and grid[1][0] > 1:
            return -1

        m = len(grid)
        n = len(grid[0])
        even = [(0,0,0)]
        odd = []
        visited = [[False] * n for _ in range(m)]
        visited[0][0] = True
        timer = 0
        for i in range(10 ** 6):
            pop_heap, push_heap = (even, odd) if timer % 2 == 0 else (odd, even)
            processing_cells = []
            while pop_heap and pop_heap[0][0] <= timer:
                processing_cells.append(heapq.heappop(pop_heap))
            for cell in processing_cells:
                if (cell[1] == m - 1) and (cell[2] == n - 1):
                    return timer
                for direction in {(0,1), (0,-1), (1,0), (-1,0)}:
                    row = cell[1] + direction[0]
                    col = cell[2] + direction[1]
                    if (0 <= row) and (row < m) and (0 <= col) and (col < n):
                        if not visited[row][col]:
                            visited[row][col] = True
                            heapq.heappush(push_heap, (grid[row][col], row, col))
            timer += 1
            if (not even) and (not odd):
                break
        return -1
```
['Python3']