You are given a 0-indexed 2D integer array grid of size m x n. Each cell has one of two values:


	0 represents an empty cell,
	1 represents an obstacle that may be removed.


You can move up, down, left, or right from and to an empty cell.

Return the minimum number of obstacles to remove so you can move from the upper left corner (0, 0) to the lower right corner (m - 1, n - 1).

&nbsp;
Example 1:

Input: grid = [[0,1,1],[1,1,0],[1,1,0]]
Output: 2
Explanation: We can remove the obstacles at (0, 1) and (0, 2) to create a path from (0, 0) to (2, 2).
It can be shown that we need to remove at least 2 obstacles, so we return 2.
Note that there may be other ways to remove 2 obstacles to create a path.


Example 2:

Input: grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]]
Output: 0
Explanation: We can move from (0, 0) to (2, 4) without removing any obstacles, so we return 0.


&nbsp;
Constraints:


	m == grid.length
	n == grid[i].length
	1 &lt;= m, n &lt;= 105
	2 &lt;= m * n &lt;= 105
	grid[i][j] is either 0 or 1.
	grid[0][0] == grid[m - 1][n - 1] == 0


class Solution:
    def minimumObstacles(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        q = [(0, 0, 0)]
        dist = [[float('inf') for _ in range(n)] for _ in range(m)]

        while q:
            size = len(q)
            for _ in range(size):
                obs, x, y = heapq.heappop(q)
                if dist[x][y] < float('inf'): continue
                obs += grid[x][y]
                dist[x][y] = obs
                if x + 1 < m: heapq.heappush(q, (obs, x + 1, y))
                if x > 0: heapq.heappush(q, (obs, x - 1, y))
                if y + 1 < n: heapq.heappush(q, (obs, x, y + 1))
                if y > 0: heapq.heappush(q, (obs, x, y - 1))
        return dist[m - 1][n - 1]
class Solution {
    int [][]grid;
    int n,m;
    boolean [][]seen;
    int []dx = new int[]{0,0,1,-1};
    int []dy = new int[]{1,-1,0,0};
    int [][]dp;
    int finalres;
    private boolean isValid(int i, int j) {
        return Math.min(i,j)>=0 && i<n && j<m && !seen[i][j];
    }
    
    private int solve(int i, int j, int cnt) {
        if(cnt>=finalres) return finalres;
        if(i == n-1 && j == m-1) {
            return cnt;
        }
        if(dp[i][j]!=Integer.MAX_VALUE) return dp[i][j];
        int res = n*m+1;
        seen[i][j]=true;
        for(int k=0;k<4;k++) {
            int newI = i+dx[k], newJ = j+dy[k];
            if(isValid(newI, newJ)) {
                res = Math.min(res, solve(newI, newJ, cnt+grid[i][j]));
            }
        }
        seen[i][j]=false;
        return dp[i][j]=Math.min(dp[i][j], res);
    }
    
    public int minimumObstacles(int[][] grid) {
        this.grid = grid;
        this.n = grid.length;
        this.m = grid[0].length;
        this.seen = new boolean[n][m];
        dp = new int[n][m];
        finalres = n*m+1;
        for(int []row:dp) Arrays.fill(row, Integer.MAX_VALUE);
        return solve(0,0,0);
    }
}
class Solution {
public:
    int minimumObstacles(vector<vector<int>>& grid) {
      int m=grid.size(), n=grid[0].size();
        vector<int> dir={0,1,0,-1,0};
        vector<vector<int>> dist(m, vector<int> (n,INT_MAX));
        vector<vector<bool>> vis(m, vector<bool>(n,0));
        deque<pair<int,int>>q;
        dist[0][0]=0;
        q.push_front({0,0});
        while(!q.empty())
        {
            auto cur=q.front();
            q.pop_front();
            int x=cur.first;
            int y=cur.second;
            for(int i=0;i<4;i++)
            {
                int cx=x+dir[i];
                int cy=y+dir[i+1];
            if(cx>=0 and cy>=0 and cx<m and cy<n)
            {
                if(!vis[cx][cy])
                {
                    dist[cx][cy]=dist[x][y]+(grid[cx][cy]==1);
                    if(grid[cx][cy]==1)
                        q.push_back({cx,cy});//obstacle cell pushed at the end
                    else
                    q.push_front({cx,cy}); //empty cell pushed on top
                    vis[cx][cy] = true;
                }
            }
        }
    }
        return dist[m-1][n-1];
    }
};
/**
 * @param {number[][]} grid
 * @return {number}
 */
var minimumObstacles = function(grid) {
    let dx=[[0,1],[0,-1],[1,0],[-1,0]];
    let distance=[];
    for(let i=0;i<grid.length;i++){
        distance[i]=[];
        for(let j=0;j<grid[i].length;j++){
            distance[i][j]=Number.MAX_SAFE_INTEGER;
        }
    }
    return bfs(0,0);

    function bfs(row,col){
        let queue=[];
        distance[row][col]=0;
        queue.push([row,col]);
        while(queue.length>0){
            let element = queue.shift();
            let row = element[0];
            let col = element[1];
            let originalDist = distance[row][col];
            for(let d=0;d<dx.length;d++){
                let i = row + dx[d][0];
                let j = col + dx[d][1];
                if(i>=0 && i<=grid.length-1 && j>=0 && j<=grid[i].length-1){
                    let dist = originalDist;
                    if(grid[i][j]===1){
                        dist++;
                    }
                    if(distance[i][j]>dist){//Update distance for this neighbour node if the new distance is smaller than the previous distance
                        queue.push([i,j]);
                        distance[i][j]=dist;
                    }

                }
            }
        }
        //return the minimum distance for last cell after completing the process
        return distance[(grid.length-1)][(grid[row].length-1)];
    }
};
Minimum Obstacle Removal to Reach Corner