Given a m * n grid, where each cell is either 0 (empty) or 1 (obstacle). In one step, you can move up, down, left or right from and to an empty cell.
Return the minimum number of steps to walk from the upper left corner (0, 0) to the lower right corner (m-1, n-1) given that you can eliminate at most k obstacles. If it is not possible to find such walk return -1.
 
Example 1:
Input: 
grid = 
[[0,0,0],
 [1,1,0],
 [0,0,0],
 [0,1,1],
 [0,0,0]], 
k = 1
Output: 6
Explanation: 
The shortest path without eliminating any obstacle is 10. 
The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2).

 
Example 2:
Input: 
grid = 
[[0,1,1],
 [1,1,1],
 [1,0,0]], 
k = 1
Output: -1
Explanation: 
We need to eliminate at least two obstacles to find such a walk.

 
Constraints:

grid.length == m
grid[0].length == n
1 <= m, n <= 40
1 <= k <= m*n
grid[i][j] == 0 or 1
grid[0][0] == grid[m-1][n-1] == 0

Difficulty: interview

Starter code:

class Solution:
    def shortestPath(self, grid: List[List[int]], k: int) -> int:
        

Solutions:
["# O(M*N*K)\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rows, cols = len(grid), len(grid[0])\n        steps, min_steps = 0, rows + cols - 2\n        if k >= min_steps - 1:\n            return min_steps\n\n        visited = [[-1] * cols for _ in range(rows)]\n        visited[0][0] = k\n        q = deque([(0, 0, k)])\n        while q:\n            steps += 1\n            prev_min = min_steps\n            for _ in range(len(q)):\n                r, c, p = q.popleft()\n                for dx, dy in [[1, 0], [-1, 0], [0, 1], [0, -1]]:\n                    x, y = c + dx, r + dy\n                    if x < 0 or x >= cols or y < 0 or y >= rows:\n                        continue\n                    kk = p-grid[y][x]\n                    if kk <= visited[y][x]: # have visited here on a better path.\n                        continue\n                    # early stop if there's shortcut (-1 because goal cell != 1)\n                    # But only applies when, comming from\n                    to_target = rows - y + cols - x - 2  # rows-r-1 + cols-c-1\n                    if kk >= to_target-1 and visited[y][x] == -1: #to_target == prev_min-1:\n                        return steps + to_target\n                    q.append((y, x, kk))\n                    visited[y][x] = kk\n                    min_steps = min(min_steps, to_target)\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if 0 == len(grid) - 1 and 0 == len(grid[0]) - 1:\n            return 0\n        \n        m, n = len(grid), len(grid[0])\n        \n        if k >= m + n - 3:\n            return m + n - 2\n        \n        seen = set()\n        q = collections.deque()\n        q.append((0, 0, k))\n        seen.add((0, 0, k))\n        steps = 0\n        direction = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        \n        while q:\n            for i in range(len(q)):\n                r, c, k = q.popleft()\n\n                for x, y in direction:\n                    R = r + x\n                    C = c + y\n                    \n                    # We are approaching a already visited cell with same k\n                    if (R, C, k) in seen:\n                        continue\n                        \n                    if R >= 0 and R < m and C >= 0 and C < n:\n                        if k > 0 and grid[R][C] == 1 and (R, C, k - 1) not in seen:\n                            q.append((R, C, k - 1))\n                            seen.add((R, C, k - 1))\n\n                        if grid[R][C] == 0 and (R, C, k) not in seen:\n                            if R == m - 1 and C == n - 1:\n                                return steps + 1\n                            q.append((R, C, k))\n                            seen.add((R, C, k))\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid:\n            return -1\n        onesDict = {(0, 0): 0}\n        m, n = len(grid), len(grid[0])\n        heap = [(self.distance(m, n, 0, 0), 0, 0, 0, 0)]\n        heapq.heapify(heap)\n        \n        while heap:\n            curHue, steps, row, col, ones = heapq.heappop(heap)\n            if (row, col) == (m - 1, n -1):\n                return curHue\n            for y, x in [(0, 1), (0, -1), (1, 0), (-1, 0)]:\n                r, c = row + y, col + x\n                if 0 <= r < m and 0 <= c < n:\n                    totalOnes = ones + grid[r][c]\n                    if totalOnes < onesDict.get((r,c), k + 1):\n                        heapq.heappush(heap, (steps + 1 + self.distance(m, n, r, c), steps + 1, r, c, totalOnes))\n                        onesDict[(r, c)] = totalOnes\n        return -1\n        \n    def distance(self, m, n, y, x):\n        return m + n - y - x - 2", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid[0])\n        n = len(grid)\n        seen = set()\n        queue = deque([(0,0,0,k)])\n        while queue:\n            x, y, total, r = queue.popleft()\n            if x == m-1 and y == n-1:\n                return total\n            \n            if x-1 >= 0 and (x-1, y, r) not in seen:\n                seen.add((x-1,y,r))\n                if grid[y][x-1] == 0:\n                    queue.append((x-1, y, total+1, r))\n                if grid[y][x-1] == 1 and r > 0:\n                    queue.append((x-1, y, total+1, r-1))\n\n            if x+1 < m and (x+1, y, r) not in seen:\n                seen.add((x+1,y,r))\n                if grid[y][x+1] == 0:\n                    queue.append((x+1, y, total+1, r))\n                if grid[y][x+1] == 1 and r > 0:\n                    queue.append((x+1, y, total+1, r-1))\n            \n            if y-1 >= 0 and (x, y-1, r) not in seen:\n                seen.add((x,y-1,r))\n                if grid[y-1][x] == 0:\n                    queue.append((x, y-1, total+1, r))\n                if grid[y-1][x] == 1 and r > 0:\n                    queue.append((x, y-1, total+1, r-1))\n            \n            if y+1 < n and (x, y+1, r) not in seen:\n                seen.add((x,y+1,r))\n                if grid[y+1][x] == 0:\n                    queue.append((x, y+1, total+1, r))\n                if grid[y+1][x] == 1 and r > 0:\n                    queue.append((x, y+1, total+1, r-1))\n                        \n        return -1\n        \n\n    \n        \n            \n        \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        q = collections.deque([(0, 0, k)])\n        visited = set((0, 0, k))\n        dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n        step = 0\n        while q:\n            for _ in range(len(q)):\n                i, j, ck = q.popleft()\n                if i == m-1 and j == n-1: return step\n                for d in dirs:\n                    ni, nj = i + d[0], j + d[1]\n                    if ni >= 0 and ni < m and nj >= 0 and nj < n and (ni, nj, ck) not in visited:\n                        if grid[ni][nj] == 0:\n                            q.append((ni, nj, ck))\n                            visited.add((ni, nj, ck))\n                        if grid[ni][nj] == 1 and ck > 0 and (ni, nj, ck - 1) not in visited:\n                            q.append((ni, nj, ck - 1))\n                            visited.add((ni, nj, ck - 1))\n            step += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # \uff08steps, k left\uff09\n        m, n = len(grid), len(grid[0])\n        dx = [-1, 1, 0, 0]\n        dy = [0, 0, -1, 1]\n        \n        queue = collections.deque([(0, 0, 0, k)])\n        seen = set([(0, 0, k)])\n        \n        while queue:\n            x, y, steps, k = queue.popleft()\n            \n            # exit immediatly when we see \n            if x == m-1 and y == n-1:\n                return steps \n            \n            for d in range(4):\n                nxt_x, nxt_y = x+dx[d], y+dy[d]\n                if (nxt_x, nxt_y, k) not in seen and  nxt_x >= 0 and nxt_x < m and nxt_y >=0 and  nxt_y < n:\n                    if grid[nxt_x][nxt_y] == 0:\n                        queue.append((nxt_x, nxt_y, steps+1, k))\n                        seen.add((nxt_x, nxt_y,k))\n                    else:\n                        if k > 0 and (nxt_x, nxt_y, k-1) not in seen:\n                            queue.append((nxt_x, nxt_y, steps+1, k-1))\n                            seen.add((nxt_x, nxt_y,k-1))\n        \n        return -1 \n                    \n                \n                        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        seen = set()\n        q = collections.deque()\n        q.append((0, 0, k))\n        seen.add((0, 0, k))\n        steps = 0\n        direction = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        \n        if 0 == m - 1 and 0 == n - 1:\n            return 0\n        \n        while q:\n            for i in range(len(q)):\n                r, c, k = q.popleft()\n\n                for x, y in direction:\n                    R = r + x\n                    C = c + y\n\n                    if (R, C, k) in seen:\n                        continue\n\n                    if R >= 0 and R < m and C >= 0 and C < n:\n                        if k > 0 and grid[R][C] == 1 and (R, C, k - 1) not in seen:\n                            q.append((R, C, k - 1))\n                            seen.add((R, C, k - 1))\n\n                        if grid[R][C] == 0 and (R, C, k) not in seen:\n                            if R == m - 1 and C == n - 1:\n                                return steps + 1\n                            q.append((R, C, k))\n                            seen.add((R, C, k))\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n, visited = len(grid), len(grid[0]), set()\n        ds = [(1, 0), (0, 1), (-1, 0), (0, -1)]\n        q = collections.deque()\n        q.append((0, 0, k))\n        visited.add((0, 0, k))\n        res, cnt, total = 0, 0, 1\n        while q:\n            i,j,r = q.popleft()\n            cnt += 1\n            if i == m - 1 and j == n - 1:\n                return res\n            for d in ds:\n                ni, nj = i + d[0], j + d[1]\n                if ni >= 0 and ni < m and nj >= 0 and nj < n and (ni, nj, r) not in visited:\n                    if grid[ni][nj] == 0 and (ni, nj, r) not in visited:\n                        visited.add((ni, nj, r))\n                        q.append((ni, nj, r))\n                    elif r > 0 and (ni, nj, r - 1) not in visited:\n                        visited.add((ni, nj, r - 1))\n                        q.append((ni, nj, r - 1))\n            if cnt == total:\n                cnt, total = 0, len(q)\n                res += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        nrow, ncol = len(grid), len(grid[0])\n        q = collections.deque([(0, 0, 0, k)])\n        \n        visited = set()\n        visited.add((0, 0, k))\n        \n        while q: \n            \n            i, j, d, life = q.popleft()\n            \n            if i == nrow -1 and j == ncol -1:\n                return d\n            \n            if grid[i][j] == 1:\n                if life == 0:\n                    continue \n                else:\n                    life -=1 \n            \n            for x, y in (i+1, j), (i-1, j), (i, j+1), (i, j-1):\n                if 0<=x<nrow and 0<=y<ncol and (x, y, life) not in visited:\n                    q.append((x, y, d+1, life))\n                    visited.add((x,y,life))\n        \n        return -1 ", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        m, n = len(grid), len(grid[0])\n        if m == n == 1: return 0\n        \n        \n        memo = [[-1] * n for _ in range(m)]\n        queue = deque()\n        queue.append( (0, 0, k, 0) )\n        visited = set()\n        visited.add((0,0,k))\n        while queue:\n            x, y, rem, res = queue.popleft()\n            if rem < 0:\n                continue\n            \n            for i, j in ( (x+1, y), (x-1, y), (x, y-1), (x, y+1) ):\n                \n                if 0 <= i < m and 0 <= j < n and (i, j, rem) not in visited: \n                    if i == m-1 and j == n-1:\n                        return res + 1\n                    visited.add((i, j, rem))\n                    if grid[i][j] == 0:\n                        queue.append( (i, j, rem, res+1) )\n                    else:\n                        queue.append( (i, j, rem-1, res+1) )\n        \n        return -1\n        \n", "# Work our way through the grid one step at a time (multiple searches running at a time given we have 4 different directions to explore at any given step).\n# Each step we check if we're at the end of our our grid, if not we continue the search.\n# Continuing the search we look at the next step of our 4 directions and make sure its valid (on the board, can afford to move an object or it's a clear 0), we record the step taken deduct 1 from k if it was a 1 location and put it back on the q.\n# We repeat this until we hit the end or run out of locations to explore in which case we couldn't make it to the end so we return -1.\n\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rows = len(grid)\n        cols = len(grid[0])\n        directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        # We'll use a deque for our BFS traversal.\n        q = collections.deque([])\n\\t\\t# (row, col, steps, k)\n        q.append((0, 0, 0, k))\n\\t\\t# Use a set (O(1) lookup) to track the locations we've visited to avoid revisiting.\n        seen = set()\n        while q:\n\\t\\t    # Pop the next location from the q.\n            r, c, steps, rk = q.popleft()\n\\t\\t\\t# If we're at the finish location return the steps, given BFS this will be\n\\t\\t\\t# guaranteed to be the first to hit this condition.\n            if r == rows-1 and c == cols - 1:\n                return steps\n\\t\\t\\t# Otherwise we'll keep travelling throught the grid in our 4 directions.\n            else:\n                for y, x in directions:\n                    nr = r + y\n                    nc = c + x\n\\t\\t\\t\\t\\t# If the new location is on the board and has not been visited.\n                    if nr >= 0 and nr < rows and nc >= 0 and nc < cols and (nr, nc, rk) not in seen:\n                        if grid[nr][nc] == 1 and rk > 0:\n                            seen.add((nr, nc, rk))\n                            q.append((nr, nc, steps + 1, rk - 1))\n                        elif grid[nr][nc] == 0:\n                            seen.add((nr, nc, rk))\n                            q.append((nr, nc, steps + 1, rk))\n\\t\\t# If we don't hit the end in our traversal we know it's not possible.\n        return -1\n        ", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        if k > (len(grid)-1 + len(grid[0])-1):\n            return len(grid)-1 + len(grid[0])-1\n        queue = deque([(0, 0, k, 0)])\n        visited = set((0, 0, k))\n        directions = [(-1,0), (0, -1), (1, 0), (0, 1)]\n        while queue:\n            row, col, k, step = queue.popleft()\n            for d in directions:\n                x = row + d[0]\n                y = col + d[1]\n                if x >= 0 and x < len(grid) and y >= 0 and y < len(grid[0]):\n                    if grid[x][y] == 1 and k > 0 and (x, y, k - 1) not in visited:\n                        if x == len(grid) -1 and y == len(grid[0]) - 1:\n                            return step + 1\n                        visited.add((x, y, k - 1))\n                        queue.append((x, y, k - 1, step + 1))\n                    if grid[x][y] == 0 and (x, y, k) not in visited:\n                        if x == len(grid) -1 and y == len(grid[0]) - 1:\n                            return step + 1\n                        visited.add((x, y, k))\n                        queue.append((x, y, k, step + 1))\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rows = len(grid)\n        cols = len(grid[0])\n\\t\\t# Directions we'll use to change our location (down, up, right, left).\n        directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        # We'll use a deque for our BFS traversal.\n        q = collections.deque([])\n\\t\\t# Append our starting details to the q.\n\\t\\t# (row, col, steps, k)\n        q.append((0, 0, 0, k))\n\\t\\t# Use a set (O(1) lookup) to track the locations we've visited to avoid revisiting.\n        seen = set()\n        while q:\n\\t\\t    # Pop the next location from the q.\n            r, c, steps, rk = q.popleft()\n\\t\\t\\t# If we're at the finish location return the steps, given BFS this will be\n\\t\\t\\t# guaranteed to be the first to hit this condition.\n            if r == rows-1 and c == cols - 1:\n                return steps\n\\t\\t\\t# Otherwise we'll keep travelling throught the grid in our 4 directions.\n            else:\n                for y, x in directions:\n                    nr = r + y\n                    nc = c + x\n\\t\\t\\t\\t\\t# If the new location is on the board and has not been visited.\n                    if nr >= 0 and nr < rows and nc >= 0 and nc < cols and (nr, nc, rk) not in seen:\n\\t\\t\\t\\t\\t    # If it's a blocker but we still have k left, we'll go there and k -= 1.\n                        if grid[nr][nc] == 1 and rk > 0:\n                            seen.add((nr, nc, rk))\n                            q.append((nr, nc, steps + 1, rk - 1))\n\\t\\t\\t\\t\\t\\t# Otherwise continue on  if it's a 0 - free location.\n                        elif grid[nr][nc] == 0:\n                            seen.add((nr, nc, rk))\n                            q.append((nr, nc, steps + 1, rk))\n\\t\\t# If we don't hit the end in our traversal we know it's not possible.\n        return -1", "class Solution:\n  def shortestPath(self, grid: List[List[int]], k: int) -> int:\n\n    row = len(grid)\n    col = len(grid[0])\n    queue = []\n    queue.append((0, 0, k, 0))\n    visited = set()\n    visited.add((0, 0, k))\n    dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n    while queue:\n      r, c, ob, step = queue.pop(0)\n      if (r, c) == (row - 1, col - 1):\n        return step\n\n      if grid[r][c] == 1:\n        if ob == 0:\n          continue\n        else:\n          ob -= 1\n\n      for dr, dc in dirs:\n        nr = r + dr\n        nc = c + dc\n        if (nr, nc, ob) in visited:\n          continue\n        if not 0 <= nr < row:\n          continue\n        if not 0 <= nc < col:\n          continue\n\n        queue.append((nr, nc, ob, step + 1))\n        visited.add((nr, nc, ob))\n        pass\n\n      pass\n\n    return -1", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        self.g = grid\n        \n        \n        \n        q = collections.deque()\n        dist = {\n            (0,0): [0]*(k+1)\n        }\n        \n        minDist = {\n            (0,0) : 0\n        }\n        \n        q.append((0,0,0))\n        target = (len(grid)-1, len(grid[0])-1)\n        \n        while q:\n            node = q.popleft()\n            \n            nodeDist = dist[(node[0], node[1])][node[2]]\n            \n            for n in self.neigh(node):                \n                nk = node[2] + (1 if grid[n[0]][n[1]] == 1 else 0)\n                \n                if n not in dist:\n                    dist[n] = [None]*(k+1)\n                \n                if nk <= k and dist[n][nk] is None:\n                    neighDist = nodeDist+1\n                    \n                    found = False\n                    for i in range(0, nk):    \n                        if dist[n][i] is not None and dist[n][i] <= neighDist:\n                            found = True\n                            \n                    if not found:\n                        dist[n][nk] = nodeDist+1\n                        minDist[n] = min(minDist[n], dist[n][nk]) if n in minDist else dist[n][nk]\n                        q.append((n[0], n[1], nk))\n        \n        #print(dist)\n        \n        return minDist[target] if target in minDist else -1\n        \n        \n        \n    def neigh(self, pos):\n        cand = [\n            (pos[0]+1, pos[1]),\n            (pos[0]-1, pos[1]),\n            (pos[0], pos[1]+1),\n            (pos[0], pos[1]-1)\n        ]\n        \n        out = []\n        \n        for c in cand:\n            if c[0] >= 0  and c[0] < len(self.g) and c[1] >= 0 and c[1] < len(self.g[0]):\n                out.append(c)\n        \n        return out\n    \n    \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid:\n            return 0\n        nr = len(grid)\n        nc = len(grid[0])\n        \n        seen = set() # (r, c, remaining k)\n        if grid[0][0] == 0:\n            start = (0,0,k)\n        elif grid[0][0] == 1:\n            start = (0,0,k-1)\n        \n        seen.add(start)\n        curr_level = [start]\n        level = 0\n        while curr_level:\n            next_level = []\n            for r, c, ob in curr_level:\n                if r == nr-1 and c == nc-1:\n                    return level\n                for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:\n                    new_r, new_c = r + dr, c + dc\n                    if 0 <= new_r < nr and 0 <= new_c < nc:\n                        if grid[new_r][new_c] == 1:\n                            if ob == 0:\n                                continue\n                            new_item = (new_r, new_c, ob-1)\n                            if new_item not in seen:\n                                seen.add(new_item)\n                                next_level.append(new_item)\n                        else: # == 0\n                            new_item = (new_r, new_c, ob)\n                            if new_item not in seen:\n                                seen.add(new_item)\n                                next_level.append(new_item)\n            curr_level = next_level\n            level += 1\n        return -1\n        \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        nrow, ncol = len(grid), len(grid[0])\n        q = [(0, 0, 0, k)]\n        \n        visited = set()\n        visited.add((0, 0, k))\n        \n        while q: \n            \n            i, j, d, life = q.pop(0)\n            \n            if i == nrow -1 and j == ncol -1:\n                return d\n            \n            if grid[i][j] == 1:\n                if life == 0:\n                    continue \n                else:\n                    life -=1 \n            \n            for x, y in (i+1, j), (i-1, j), (i, j+1), (i, j-1):\n                if 0<=x<nrow and 0<=y<ncol and (x, y, life) not in visited:\n                    q.append((x, y, d+1, life))\n                    visited.add((x,y,life))\n        \n        return -1 ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # BFS\n        m, n = len(grid), len(grid[0])\n        initial_state = (0, 0, k) # (i, j, remaining obstacle elimination ability)\n        q = collections.deque()\n        q.append(initial_state)\n        visited = set()\n        visited.add(initial_state)\n        dist = 0\n        directions = ((-1, 0), (1, 0), (0, -1), (0, 1))\n        \n        while q:\n            for _ in range(len(q)):\n                i, j, r = q.popleft()\n                if r < 0:\n                    continue\n                if i == m-1 and j == n-1:\n                    return dist\n                for dx, dy in directions:\n                    nx, ny = i + dx, j + dy\n                    if 0 <= nx < m and 0 <= ny < n:\n                        if grid[nx][ny] == 0:\n                            next_state = (nx, ny, r)\n                        else:\n                            next_state = (nx, ny, r-1)\n                        if next_state not in visited:\n                            q.append(next_state)\n                            visited.add(next_state)\n                        \n            dist += 1\n            \n        return -1\n            \n                \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # BFS\n        \n        queue = collections.deque([(0,0,0,0)])\n        m = len(grid)\n        n = len(grid[0])\n        visited = {}\n        visited[(0,0)] = 0\n        steps=0\n        while queue:\n            x,y,used_k,steps = queue.popleft()\n            # visited.add((x,y))\n            if x==m-1 and y==n-1:\n                return steps\n            for i,j in [[0,1],[0,-1],[1,0],[-1,0]]:\n                nx,ny = x+i,y+j\n                if 0<=nx<m and 0<=ny<n:\n                    if visited.get((nx,ny),float('inf'))<=used_k:\n                        continue\n                        \n                    if used_k>=k:\n                        if grid[nx][ny]==1:\n                            continue\n                        else:\n                            visited[(nx,ny)] = used_k\n                            queue.append([nx,ny,used_k,steps+1])\n                    else:\n                        if grid[nx][ny]==1:\n                            visited[(nx,ny)] = used_k+1\n                            queue.append([nx,ny,used_k+1,steps+1])\n                        else:\n                            visited[(nx,ny)] = used_k\n                            queue.append([nx,ny,used_k,steps+1])\n                \n        return -1\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n#         m, n = len(grid), len(grid[0])\n#         q = collections.deque([[0, 0, 0]])    # row, col, num of obstables met so far\n#         visited = {(0, 0): 0}                 # row, col   =>   num of obstables met so far\n#         steps = 0\n        \n#         while q:\n#             size = len(q)\n#             for _ in range(size):\n#                 r, c, obs = q.popleft()\n#                 if obs > k: continue\n#                 if r == m - 1 and c == n - 1: \n#                     return steps\n#                 for r2, c2 in [[r+1, c], [r-1, c], [r, c+1], [r, c-1]]:\n#                     if 0 <= r2 < m and 0 <= c2 < n:\n#                         next_obs = obs + 1 if grid[r2][c2] == 1 else obs\n#                         if next_obs < visited.get((r2, c2), float('inf')):\n#                             visited[(r2, c2)] = next_obs\n#                             q.append([r2, c2, next_obs])\n#             steps += 1\n        \n#         return -1\n", "class Solution:\n        def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n            q = [(0,0,k,0)]\n            m, n = len(grid), len(grid[0])\n\n            visited = {(0,0,k)}\n\n            while q:\n                r, c, ob, step = q.pop(0)\n                if (r, c) == (m-1, n-1):\n                    return step\n\n                if grid[r][c] == 1:\n                    if ob == 0:\n                        continue\n                    else:\n                        ob -= 1\n\n                for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:\n                    nr, nc = r+dr, c+dc\n                    if 0<=nr<m and 0<=nc<n and (nr, nc, ob) not in visited:\n                        q.append((nr, nc, ob, step+1))\n                        visited.add((nr, nc, ob))\n\n            return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = [(0,0,k,0)]\n        m, n = len(grid), len(grid[0])\n        \n        visited = {(0,0,k)}\n\n        while q:\n            r, c, ob, step = q.pop(0)\n            if (r, c) == (m-1, n-1):\n                return step\n\n            if grid[r][c] == 1:\n                if ob == 0:\n                    continue\n                else:\n                    ob -= 1\n\n            for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:\n                nr, nc = r+dr, c+dc\n                if 0<=nr<m and 0<=nc<n and (nr, nc, ob) not in visited:\n                    q.append((nr, nc, ob, step+1))\n                    visited.add((nr, nc, ob))\n                    \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        q = [(0,0,k,0)]\n        m, n = len(grid), len(grid[0])\n        \n        visited = {(0,0,k)}\n\n        while q:\n            r, c, ob, step = q.pop(0)\n            if (r, c) == (m-1, n-1):\n                return step\n\n            if grid[r][c] == 1:\n                if ob == 0:\n                    continue\n                else:\n                    ob -= 1\n\n            for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:\n                nr, nc = r+dr, c+dc\n                if 0<=nr<m and 0<=nc<n and (nr, nc, ob) not in visited:\n                    q.append((nr, nc, ob, step+1))\n                    visited.add((nr, nc, ob))\n                    \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        q = [(0,0,k,0)]\n        m, n = len(grid), len(grid[0])\n        \n        visited = {(0,0,k)}\n\n        while q:\n            r, c, ob, step = q.pop(0)\n            if (r, c) == (m-1, n-1):\n                return step\n\n            if grid[r][c] == 1:\n                if ob == 0:\n                    continue\n                else:\n                    ob -= 1\n\n            for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:\n                nr, nc = r+dr, c+dc\n                if 0<=nr<m and 0<=nc<n and (nr, nc, ob) not in visited:\n                    q.append((nr, nc, ob, step+1))\n                    visited.add((nr, nc, ob))\n                    \n        return -1\n", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        move = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n        \n        queue = collections.deque([(0, 0, k)])\n        seen = set([(0, 0, k)])\n        level = 0\n        while queue:\n            #print(queue, seen)\n            size = len(queue)\n            for _ in range(size):\n                x, y, remain = queue.popleft()\n                if x == m-1 and y == n-1:\n                    return level\n                for dx, dy in move:\n                    newX, newY = x + dx, y + dy\n                    if 0 <= newX < m and 0 <= newY < n:\n                        if grid[newX][newY] == 0:\n                            if (newX, newY, remain) not in seen:\n                                queue.append((newX, newY, remain))\n                                seen.add((newX, newY, remain))\n                        else:\n                            if remain > 0:\n                                if (newX, newY, remain-1) not in seen:\n                                    queue.append((newX, newY, remain-1))\n                                    seen.add((newX, newY, remain - 1))\n            level += 1\n        return -1\n                    \n        \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        N, M = len(grid), len(grid[0])\n        moves = [(-1,0),(1,0),(0,-1),(0,1)]\n        \n        queue = [(N-1,M-1,k,0)]\n        visited = set([(N-1,M-1,k)])\n        for i, j, k, m in queue:\n            if i == 0 and j == 0:\n                return m\n            \n            for move in moves:\n                ni, nj = i+move[0], j+move[1]\n                if N > ni >= 0 <= nj < M:\n                    nk = k-grid[ni][nj]\n                    if nk >= 0 and (ni, nj, nk) not in visited:\n                        #print(ni, nj, nk, m-1)\n                        visited.add((ni,nj,nk))\n                        queue.append((ni,nj,nk,m+1))\n        return -1", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n\n        queue = collections.deque()\n        queue.append([0, 0, k, 0])\n        visited = set((0, 0, k))\n\n        while queue:\n            x, y, k, step = queue.popleft()\n            if x == m - 1 and y == n - 1:\n                return step\n            for nx, ny in ((x + 1, y), (x, y + 1), (x -1, y), (x, y - 1)):\n                if 0 <= nx < m and 0 <= ny < n:\n                    nk = k - grid[nx][ny]\n                    if nk >= 0 and not (nx, ny, nk) in visited:\n                        visited.add((nx, ny, nk))\n                        queue.append((nx, ny, nk, step + 1))\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        N, M = len(grid), len(grid[0])\n        moves = [(-1,0),(1,0),(0,-1),(0,1)]\n        \n        queue = collections.deque([(N-1,M-1,k,0)])\n        visited = set([(N-1,M-1,k)])\n        while queue:\n            i, j, k, m = queue.popleft()\n            if i == 0 and j == 0:\n                return m\n            \n            for move in moves:\n                ni, nj = i+move[0], j+move[1]\n                if N > ni >= 0 <= nj < M:\n                    nk = k-grid[ni][nj]\n                    if nk >= 0 and (ni, nj, nk) not in visited:\n                        #print(ni, nj, nk, m-1)\n                        visited.add((ni,nj,nk))\n                        queue.append((ni,nj,nk,m+1))\n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        dq = deque()\n        dq.append((0, 0, k, 0))\n        visited = set()\n        visited.add((0, 0, k))\n        \n        while dq:\n            cur = dq.popleft()\n            row = cur[0]\n            col = cur[1]\n            elm = cur[2]\n            pth = cur[3]\n            if row == len(grid)-1 and col == len(grid[0])-1:\n                return pth\n            \n            if col < len(grid[0])-1:\n                if grid[row][col+1] == 1:\n                    if elm > 0 and (row, col+1, elm-1) not in visited:\n                        dq.append((row, col+1, elm-1, pth+1))\n                        visited.add((row, col+1, elm-1))\n                elif (row, col+1, elm) not in visited:\n                    dq.append((row, col+1, elm, pth+1))\n                    visited.add((row, col+1, elm))\n            \n            if row < len(grid)-1:\n                if grid[row+1][col] == 1:\n                    if elm > 0 and (row+1, col, elm-1) not in visited:\n                        dq.append((row+1, col, elm-1, pth+1))\n                        visited.add((row+1, col, elm-1))\n                elif (row+1, col, elm) not in visited:\n                    dq.append((row+1, col, elm, pth+1))\n                    visited.add((row+1, col, elm))\n                    \n            if row > 0:\n                if grid[row-1][col] == 1:\n                    if elm > 0 and (row-1, col, elm-1) not in visited:\n                        dq.append((row-1, col, elm-1, pth+1))\n                        visited.add((row-1, col, elm-1, pth+1))\n                elif (row-1, col, elm) not in visited:\n                    dq.append((row-1, col, elm, pth+1))\n                    visited.add((row-1, col, elm))\n                    \n            if col > 0:\n                if grid[row][col-1] == 1:\n                    if elm > 0 and (row, col-1, elm-1) not in visited:\n                        dq.append((row, col-1, elm-1, pth+1))\n                        visited.add((row, col-1, elm-1))\n                    elif (row, col-1, elm) not in visited:\n                        dq.append((row, col-1, elm, pth+1))\n                        visited.add((row, col-1, elm))\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q=deque([(0,0,k)])\n        visited=set()\n        m=len(grid)\n        n=len(grid[0])\n        res=0\n        while q:\n            l=len(q)\n            for _ in range(l):\n                i,j,k=q.popleft()\n                if i==m-1 and j==n-1:\n                    return res\n                for ii,jj in [[i+1,j],[i-1,j],[i,j-1],[i,j+1]]:\n                    if 0<=ii<m and 0<=jj<n:\n                        if grid[ii][jj]==0:\n                            if (ii,jj,k) not in visited:\n                                visited.add((ii,jj,k))\n                                q.append((ii,jj,k))\n                        else:\n                            if k>0 and (ii,jj,k-1) not in visited:\n                                visited.add((ii,jj,k-1))\n                                q.append((ii,jj,k-1))\n            res+=1\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        from collections import deque, defaultdict\n        moves = [ [-1, 0], [1, 0], [0, -1], [0, 1]]\n        rows = len(grid)\n        cols = len(grid[0])\n\n        seen = set() #defaultdict(lambda: float(\\\"inf\\\"))\n        queue = deque()\n        queue.append((0, 0, k, 0))\n        \n        while len(queue) > 0:\n            row, col, eliminations_left, path_length = queue.popleft()\n            \n            if row == rows-1 and col == cols-1:\n                return path_length\n            \n            for move in moves:\n                next_row, next_col = row + move[0], col + move[1]\n                \n                if not (0 <= next_row < rows) or not (0 <= next_col < cols):\n                    continue\n                \n                if (next_row, next_col, eliminations_left) in seen:\n                    continue\n                \n                if grid[next_row][next_col] == 1:\n                    if eliminations_left > 0:\n                        seen.add((next_row, next_col, eliminations_left))\n                        queue.append((next_row, next_col, eliminations_left-1, path_length+1))\n                else:\n                    seen.add((next_row, next_col, eliminations_left))\n                    queue.append((next_row, next_col, eliminations_left, path_length+1))\n\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        nrows = len(grid)\n        ncols = len(grid[0])\n        if nrows == 1 and ncols ==1:\n            return 0\n        step = 1\n        \n        if k > (nrows-1 + ncols-1):\n            return (nrows-1+ncols-1)\n        \n        q = collections.deque()\n        visited = set([(0,0, k)])\n        q.append((0,0, k, step))\n        \n        def neigh(x,y):\n            tocheck = [(x+1,y), (x, y+1), (x-1, y), (x, y-1)]\n            nlist = []\n            for n in tocheck:\n                if 0<=n[0]<nrows and 0<= n[1]<ncols:\n                    nlist.append(n)\n            return nlist\n        \n        while(q):\n            i, j, k, step  = q.popleft()\n            neighs = neigh(i,j)\n            if i == nrows-1 and j == ncols-1:\n                return step\n            if neighs:\n                for n in neighs:\n                    if grid[n[0]][n[1]] == 1 and k>0 and (n[0], n[1], k-1) not in visited:\n                        q.append((n[0], n[1], k-1, step+1))\n                        visited.add((n[0], n[1], k-1))\n                        \n                    if grid[n[0]][n[1]] == 0 and (n[0], n[1], k) not in visited:\n                        if n[0] == nrows-1 and n[1] == ncols-1:\n                            return step\n                        q.append((n[0], n[1], k, step+1))\n                        visited.add((n[0], n[1], k))\n        \n        return -1\n    \n    \n    # 1091 is shortest path in binary matrix\n    # time complexity is O(m*n*k)\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        start = (0, 0, k)\n        queue = collections.deque([(0, start)])\n        visited = set([start])\n        while queue:\n            steps, (i, j, k) = queue.popleft()\n            if i == m-1 and j == n-1:\n                return steps\n            for dx, dy in [(0,1), (1,0), (0,-1), (-1,0)]:\n                x, y = i + dx, j + dy\n                if 0 <= x < m and 0 <= y < n:\n                    state = (x, y, k-grid[x][y])\n                    if state not in visited and state[2] >= 0:\n                        queue.append((steps+1, state))\n                        visited.add(state)\n        return -1", "class Solution:\n    from collections import deque\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        m,n = len(grid), len(grid[0])\n        D = [[-1,0],[1,0],[0,1],[0,-1]]\n        \n        Q = deque([])\n        Q.append((0,0,k,0))\n        visited = set()\n        \n        while(Q):\n            x,y,rem,lv = Q.popleft()\n            if x==m-1 and y==n-1:\n                return lv\n            for dx,dy in D:\n                if 0<=x+dx<m and 0<=y+dy<n and (x+dx,y+dy,rem) not in visited:\n                    visited.add((x+dx,y+dy,rem))\n                    if grid[x+dx][y+dy] == 0:\n                        Q.append((x+dx,y+dy,rem,lv+1))\n                    elif grid[x+dx][y+dy] == 1 and rem>0:\n                        Q.append((x+dx,y+dy,rem-1,lv+1))\n        return -1\n                        \n        \n           \n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n      if len(grid) == 1 and len(grid[0]) == 1:\n        return 0\n      queue = deque([(0,0,k,0)])#i,j,free eliminate chance, steps\n      directions = [[0,1], [0,-1], [-1,0], [1,0]]\n      visited = set([(0,0,k)])\n    \n      M, N = len(grid), len(grid[0])\n      while queue:\n        i, j, m, steps = queue.popleft()\n        for dx, dy in directions:\n          x = dx + i\n          y = dy + j\n          if 0 <= x < M and 0 <= y < N:\n            if grid[x][y] == 1 and m > 0 and (x, y, m-1) not in visited:\n              visited.add((x,y,m-1))\n              queue.append((x, y, m-1, steps+1))\n              \n            if grid[x][y] == 0 and  (x, y, m) not in visited:\n              if x == M-1 and y == N-1:\n                return steps + 1\n              \n              visited.add((x, y, m))\n              queue.append((x, y, m, steps+1))\n      return -1\n          \n      \n", "\\\"\\\"\\\"\nBecause we are trying to find the shortest path, use BFS here to exit immediately when a path reaches the bottom right most cell.\nUse a set to keep track of already visited paths. We only need to keep track of the row, column, and the eliminate obstacle usage count. We don't need to keep track of the steps because remember we are using BFS for the shortest path. That means there is no value storing a 4th piece of the data, the current steps. This will reduce the amount of repeat work.\nm = rows\nn = columns\nk = allowed elimination usages\n\nTime Complexity\nO(m*n*k) time complexity\nThis is because for every cell (m*n), in the worst case we have to put that cell into the queue/bfs k times.\n\nRuntime: 68 ms, faster than 33.33% of Python3 online submissions\n\nSpace Complexity\nO(m*n*k) space complexity\nThis is because for every cell (m*n), in the worst case we have to put that cell into the queue/bfs k times which means we need to worst case store all of those steps/paths in the visited set.\n\\\"\\\"\\\"\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = collections.deque([(0, 0, 0, 0)])\n        m, n = len(grid), len(grid[0])\n        visited = set()\n         \n        while q:\n            x, y, obstacle, path = q.popleft()\n            for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n                if 0 <= i < m and 0 <= j < n:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n                        visited.add((i, j, obstacle + 1))\n                        q.append((i, j, obstacle + 1, path + 1))\n                    if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n                        if (i, j) == (m - 1, n - 1):\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        q.append((i, j, obstacle, path + 1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: return -1\n        m, n, direction = len(grid), len(grid[0]), [[0, 1], [0, -1], [1, 0], [-1, 0]]\n        visited = [[[False] * (k + 1) for _ in range(n)] for _ in range(m)]\n        visited[0][0][0] = True\n        \n        count, queue = 0, deque([[0, 0, 0]])\n        \n        while len(queue) > 0:\n            size = len(queue)\n            for i in range(size):\n                cur = queue.popleft()\n                if cur[0] == m - 1 and cur[1] == n - 1: return count\n                for d in direction:\n                    r, c, tmpK = cur[0] + d[0], cur[1] + d[1], cur[2]\n                    if r >= 0 and c >= 0 and r < m and c < n:\n                        if grid[r][c] == 1: tmpK += 1\n                        \n                        if tmpK <= k and not visited[r][c][tmpK]:\n                            visited[r][c][tmpK] = True\n                            queue.append([r, c, tmpK])\n                    \n            count += 1\n        return -1\n", "\\\"\\\"\\\"\nBecause we are trying to find the shortest path, use BFS here to exit immediately when a path reaches the bottom right most cell.\nUse a set to keep track of already visited paths. We only need to keep track of the row, column, and the eliminate obstacle usage count. We don't need to keep track of the steps because remember we are using BFS for the shortest path. That means there is no value storing a 4th piece of the data, the current steps. This will reduce the amount of repeat work.\nm = rows\nn = columns\nk = allowed elimination usages\n\nTime Complexity\nO(m*n*k) time complexity\nThis is because for every cell (m*n), in the worst case we have to put that cell into the queue/bfs k times.\n\nRuntime: 68 ms, faster than 33.33% of Python3 online submissions\n\nSpace Complexity\nO(m*n*k) space complexity\nThis is because for every cell (m*n), in the worst case we have to put that cell into the queue/bfs k times which means we need to worst case store all of those steps/paths in the visited set.\n\\\"\\\"\\\"\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        queue = collections.deque([(0, 0, 0, 0)])\n        Row, Col = len(grid), len(grid[0])\n        visited = set()\n         \n        while queue:\n            r, c, obstacle, path = queue.popleft()\n            for x, y in ((r+1, c), (r-1, c), (r, c+1), (r, c-1)):\n                if 0 <= x < Row and 0 <= y < Col:\n                    if grid[x][y] == 1 and obstacle < k and (x, y, obstacle + 1) not in visited:\n                        visited.add((x, y, obstacle + 1))\n                        queue.append((x, y, obstacle + 1, path + 1))\n                    if grid[x][y] == 0 and (x, y, obstacle) not in visited:    \n                        if (x, y) == (Row - 1, Col - 1):\n                            return path + 1\n                        visited.add((x, y, obstacle))\n                        queue.append((x, y, obstacle, path + 1))\n                        \n        return -1", "from collections import deque\ndirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        dq = deque([(0, 0, k)])\n        visited = set([(0, 0, k)])\n        step = 0\n        while dq:\n            size = len(dq)\n            for i in range(size):\n                r, c, p = dq.popleft() # p: remaining k\n                if r == m - 1 and c == n - 1:\n                    return step\n                for d in dirs:\n                    nr, nc = r + d[0], c + d[1]\n                    if not (0 <= nr < m) or not (0 <= nc < n):\n                        continue\n                    elif grid[nr][nc] == 0:\n                        if (nr, nc, p) not in visited:\n                            visited.add((nr, nc, p))\n                            dq.append((nr, nc, p))\n                    elif grid[nr][nc] == 1:\n                        if p > 0 and (nr, nc, p - 1) not in visited:\n                            visited.add((nr, nc, p - 1))\n                            dq.append((nr, nc, p - 1))\n            step += 1\n        return -1", "\\\"\\\"\\\"\nhttps://www.youtube.com/watch?v=RQxws-5elag\n\nBecause we are trying to find the shortest path, use BFS here to exit immediately when a path reaches the bottom right most cell.\nUse a set to keep track of already visited paths. We only need to keep track of the row, column, and the eliminate obstacle usage count. We don't need to keep track of the steps because remember we are using BFS for the shortest path. That means there is no value storing a 4th piece of the data, the current steps. This will reduce the amount of repeat work.\nm = rows\nn = columns\nk = allowed elimination usages\n\nTime Complexity\nO(m*n*k) time complexity\nThis is because for every cell (m*n), in the worst case we have to put that cell into the queue/bfs k times.\n\nRuntime: 68 ms, faster than 33.33% of Python3 online submissions\n\nSpace Complexity\nO(m*n*k) space complexity\nThis is because for every cell (m*n), in the worst case we have to put that cell into the queue/bfs k times which means we need to worst case store all of those steps/paths in the visited set.\n\\\"\\\"\\\"\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        queue = collections.deque([(0, 0, 0, 0)])\n        Row, Col = len(grid), len(grid[0])\n        visited = set()\n         \n        while queue:\n            r, c, obstacle, steps = queue.popleft()\n            for x, y in ((r+1, c), (r-1, c), (r, c+1), (r, c-1)):\n                if 0 <= x < Row and 0 <= y < Col:\n                    if grid[x][y] == 1 and obstacle < k and (x, y, obstacle + 1) not in visited:\n                        visited.add((x, y, obstacle + 1))\n                        queue.append((x, y, obstacle + 1, steps + 1))\n                    if grid[x][y] == 0 and (x, y, obstacle) not in visited:    \n                        if (x, y) == (Row - 1, Col - 1):\n                            return steps + 1\n                        visited.add((x, y, obstacle))\n                        queue.append((x, y, obstacle, steps + 1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid, k):\n        if not grid or not grid[0]:\n            return -1\n        n = len(grid)\n        m = len(grid[0])\n        q = [[0, 0, 0, k]]  # len, row,col, obstacles is left\n        seen = set()\n        seen.add((0, 0, k))\n        while q:\n            d, r, c, ob = q.pop(0)\n            if r == n - 1 and c == m - 1:\n                return d\n            if grid[r][c] == 1:\n                if ob == 0:\n                    continue\n                ob -= 1\n            for dr, dc in [[0, 1], [1, 0], [0, -1], [-1, 0]]:\n                nr = r + dr\n                nc = c + dc\n                if 0 <= nr < n and 0 <= nc < m:\n                    if (nr, nc, ob) in seen:\n                        continue\n                    q.append([d + 1, nr, nc, ob])\n                    seen.add((nr, nc, ob))\n        return -1\n\n", "# import functools\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         r, c = len(grid), len(grid[0])\n#         qu = deque([[0,0,0,0]])\n#         ans = inf\n#         visited = set()\n#         while qu:\n#             i,j,cnt,length = qu.popleft()\n#             visited.add((i,j,cnt))\n#             if (i,j) == (r-1,c-1): return length\n#             for x, y in [[i-1,j],[i+1,j],[i,j-1],[i,j+1]]:\n#                 if 0<=x<r and 0<=y<c:\n#                     new_cnt = cnt if grid[x][y] == 0 else cnt+1\n#                     if new_cnt<=k and (x,y,new_cnt) not in visited:\n#                         qu.append([x,y,new_cnt,length+1])\n#         return -1\n#         while q:\n#             x, y, obstacle, path = q.popleft()\n#             for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n#                 if 0 <= i < m and 0 <= j < n:\n#                     if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n#                         visited.add((i, j, obstacle + 1))\n#                         q.append((i, j, obstacle + 1, path + 1))\n#                     if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n#                         if (i, j) == (m - 1, n - 1):\n#                             return path + 1\n#                         visited.add((i, j, obstacle))\n#                         q.append((i, j, obstacle, path + 1))\n                        \n#         return -1\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = collections.deque([(0, 0, 0, 0)])\n        m, n = len(grid), len(grid[0])\n        visited = set()\n         \n        while q:\n            x, y, obstacle, path = q.popleft()\n            for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n                if 0 <= i < m and 0 <= j < n:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n                        visited.add((i, j, obstacle + 1))\n                        q.append((i, j, obstacle + 1, path + 1))\n                    if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n                        if (i, j) == (m - 1, n - 1):\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        q.append((i, j, obstacle, path + 1))\n                        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rowlen = len(grid)\n        collen = len(grid[0])\n                \n        if k > (len(grid)-1 + len(grid[0])-1):\n            return len(grid)-1 + len(grid[0])-1\n        \n        visited = set()\n        visited.add((0,0,k))\n        \n        q = deque([(0,0,k, 0)])\n        \n        def get_nexts(x,y):\n            return [(nx,ny) for (nx,ny) in [(x+1,y), (x-1, y), (x, y+1), (x, y-1)] if 0<=nx<rowlen and 0<=ny<collen]\n        \n        while q:\n            x,y,k,path_count = q.popleft()       \n            \n            if (x,y) == (rowlen-1, collen-1): return path_count\n                        \n            nexts = get_nexts(x,y)\n            \n            for nx,ny in nexts:                \n                if grid[nx][ny] == 1 and not k: continue\n                if grid[nx][ny] == 1 and (nx,ny,k-1) in visited: continue\n                if grid[nx][ny] == 0 and (nx,ny,k) in visited: continue\n                    \n                if grid[nx][ny] == 1:\n                    visited.add((nx,ny,k-1))\n                    q.append((nx,ny,k-1,path_count+1))\n                else:\n                    if (nx,ny) == (rowlen-1, collen-1): return path_count+1\n                    visited.add((nx,ny,k))\n                    q.append((nx,ny,k,path_count+1))                \n        \n        return -1\n            \n", "class Solution:\n    # BFS\n    # To avoid TLE, if already visited (i,j) with given new_k don't visit again (Complexity: O((m*n)*k) == O((m*n)^2)) \n    # OR if lvl_cnt > m*n then return -1\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        HT, WT = len(grid), len(grid[0])\n        TARGET = (HT-1, WT-1)\n        \n        from collections import deque\n        q = deque([(0,0,k)])\n        visited = set(q)\n        lvl_cnt = 0\n        \n        while q:\n            for i in range(len(q)):\n                r,c,new_k = q.popleft()\n                if (r,c) == TARGET: return lvl_cnt\n                for i,j in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:\n                    if 0 <= i < HT and 0 <= j < WT:\n                        if grid[i][j] == 0 and (i,j,new_k) not in visited:\n                            q.append((i,j,new_k))\n                            visited.add((i,j,new_k))\n                        elif grid[i][j] == 1 and new_k > 0 and (i,j,new_k-1) not in visited:\n                            q.append((i,j,new_k-1))\n                            visited.add((i,j,new_k-1))\n            lvl_cnt += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return int()\n        \n        queue       = collections.deque([(0, 0, 0, 0)])\n        row, col    = len(grid), len(grid[0])\n        visited     = set()\n        \n        while queue:\n            x, y, obstacle, path    = queue.popleft()\n            \n            for i, j in (x+1, y), (x-1, y), (x, y-1), (x, y+1):\n                if 0 <= i < row and 0 <= j < col:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle+1) not in visited:\n                        visited.add((i, j, obstacle+1))\n                        queue.append((i, j, obstacle+1, path+1))\n                    elif grid[i][j] == 0 and (i, j, obstacle) not in visited:\n                        if i == row - 1 and j == col - 1:\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        queue.append((i, j, obstacle, path + 1))\n        \n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque([(0, 0, 0, 0)])\n        visited = set()\n        visited.add((0, 0, 0))\n        m = len(grid)\n        n = len(grid[0])\n        directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]\n\n        while queue:\n            r, c, removed, count = queue.popleft()\n\n            if r == m - 1 and c == n - 1:\n                return count\n            \n            for inc_r, inc_c in directions:\n                new_r = r + inc_r\n                new_c = c + inc_c\n                \n                if 0 <= new_r < m and 0 <= new_c < n:\n                    if removed < k and (new_r, new_c, removed+1) not in visited and grid[new_r][new_c] == 1:\n                        queue.append((new_r, new_c, removed+1, count+1))\n                        visited.add((new_r, new_c, removed+1))\n                    elif (new_r, new_c, removed) not in visited and grid[new_r][new_c] == 0:\n                        queue.append((new_r, new_c, removed, count+1))\n                        visited.add((new_r, new_c, removed))\n\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int: # 43\n        \n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = collections.deque([(0, 0, 0, 0)])\n        m, n = len(grid), len(grid[0])\n        visited = set()\n         \n        while q:\n            x, y, obstacle, path = q.popleft()\n            for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n                if 0 <= i < m and 0 <= j < n:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n                        visited.add((i, j, obstacle + 1))\n                        q.append((i, j, obstacle + 1, path + 1))\n                    if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n                        if (i, j) == (m - 1, n - 1):\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        q.append((i, j, obstacle, path + 1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        visited = set()\n        q = collections.deque([(0,0,0,0)])\n        r,c = len(grid), len(grid[0])\n        while q:\n            x, y, obs, path = q.popleft()\n            for i, j in [(x,y+1),(x,y-1),(x+1,y),(x-1,y)]:\n                if 0 <= i < r and 0 <= j < c:\n                    if grid[i][j] == 0 and (i,j,obs) not in visited:\n                        if i == r- 1 and j == c - 1:\n                            return path+1   \n                        q.append([i,j,obs,path+1])\n                        visited.add((i,j,obs))\n                    if grid[i][j] == 1 and obs < k and ((i,j,obs+1) not in visited):\n                        q.append([i,j,obs+1,path+1])\n                        visited.add((i,j,obs+1))\n        return -1 ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        q = deque([(0, 0, k)])\n        visited = set([(0, 0, k)])\n        steps = 0\n        while q:\n            size = len(q)\n            for _ in range(size):\n                i, j, remain = q.popleft()\n                if (i, j) == (m-1, n-1):\n                    return steps\n                for x, y in (i, j-1), (i-1, j), (i, j+1), (i+1, j):\n                    if m > x >= 0 <= y < n:\n                        if grid[x][y] == 0 and (x, y, remain) not in visited:\n                            q.append((x, y, remain))\n                            visited.add((x, y, remain))\n                        elif grid[x][y] == 1 and remain > 0 and (x, y, remain-1) not in visited:\n                            q.append((x, y, remain - 1))\n                            visited.add((x, y, remain - 1))\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: return -1\n        m, n, direction = len(grid), len(grid[0]), [[0, 1], [0, -1], [1, 0], [-1, 0]]\n        visited = [[[False] * (k + 1) for _ in range(n)] for _ in range(m)]\n        visited[0][0][0] = True\n        \n        count, queue = 0, [[0, 0, 0]]\n        \n        while len(queue) > 0:\n            size = len(queue)\n            for i in range(size):\n                cur = queue.pop(0)\n                if cur[0] == m - 1 and cur[1] == n - 1: return count\n                for d in direction:\n                    r, c, tmpK = cur[0] + d[0], cur[1] + d[1], cur[2]\n                    if r >= 0 and c >= 0 and r < m and c < n:\n                        if grid[r][c] == 1: tmpK += 1\n                        \n                        if tmpK <= k and not visited[r][c][tmpK]:\n                            visited[r][c][tmpK] = True\n                            queue.append([r, c, tmpK])\n                    \n            count += 1\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = collections.deque([(0, 0, 0, 0)])\n        m, n = len(grid), len(grid[0])\n        visited = set()\n        \n        while q:\n            x, y, obstacle, path = q.popleft()\n            for a, b in [(0,1),(0,-1),(1,0),(-1,0)]:\n                i, j = a+x, b+y\n                if 0 <= i < m and 0 <= j < n:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n                        visited.add((i, j, obstacle + 1))\n                        q.append((i, j, obstacle + 1, path + 1))\n                    if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n                        if (i, j) == (m - 1, n - 1):\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        q.append((i, j, obstacle, path + 1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        seen = set()\n        q = collections.deque()\n        q.append((0, 0, k))\n        seen.add((0, 0, k))\n        steps = 0\n        direction = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        \n        if 0 == m - 1 and 0 == n - 1:\n            return 0\n        \n        while q:\n            for i in range(len(q)):\n                r, c, k = q.popleft()\n\n                for x, y in direction:\n                    R = r + x\n                    C = c + y\n\n                    # if (R, C, k) in seen:\n                    #     continue\n\n                    if R >= 0 and R < m and C >= 0 and C < n:\n                        if k > 0 and grid[R][C] == 1 and (R, C, k - 1) not in seen:\n                            q.append((R, C, k - 1))\n                            seen.add((R, C, k - 1))\n\n                        if grid[R][C] == 0 and (R, C, k) not in seen:\n                            if R == m - 1 and C == n - 1:\n                                return steps + 1\n                            q.append((R, C, k))\n                            seen.add((R, C, k))\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        nrows = len(grid)\n        ncols = len(grid[0])\n        if nrows == 1 and ncols ==1:\n            return 0\n        step = 1\n        \n        if k > nrows-1 + ncols-1:\n            return nrows-1+ncols-1\n        \n        q = collections.deque()\n        visited = set([(0,0, k)])\n        q.append((0,0, k, step))\n        \n        def neigh(x,y):\n            tocheck = [(x+1,y), (x, y+1), (x-1, y), (x, y-1)]\n            nlist = []\n            for n in tocheck:\n                if 0<=n[0]<nrows and 0<= n[1]<ncols:\n                    nlist.append(n)\n            return nlist\n        \n        while(q):\n            i, j, k, step  = q.popleft()\n            neighs = neigh(i,j)\n            if i == nrows-1 and j == ncols-1:\n                return step\n            if neighs:\n                for n in neighs:\n                    if grid[n[0]][n[1]] == 1 and k>0 and (n[0], n[1], k-1) not in visited:\n                        q.append((n[0], n[1], k-1, step+1))\n                        visited.add((n[0], n[1], k-1))\n                        \n                    if grid[n[0]][n[1]] == 0 and (n[0], n[1], k) not in visited:\n                        if n[0] == nrows-1 and n[1] == ncols-1:\n                            return step\n                        q.append((n[0], n[1], k, step+1))\n                        visited.add((n[0], n[1], k))\n        \n        return -1\n    \n    \n    # 1091 is shortest path in binary matrix\n    # time complexity is O(m*n*k)\n            \n", "class Solution:\n    # TLE\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = set()\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and (ii, jj, k) not in seen:\n                            seen.add((ii, jj, k))\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and (ii, jj, k-1) not in seen:\n                            seen.add((ii, jj, k-1))\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        seen = set()\n        q = collections.deque()\n        q.append((0, 0, k))\n        seen.add((0, 0, k))\n        steps = 0\n        direction = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        \n        if 0 == m - 1 and 0 == n - 1:\n            return 0\n        \n        while q:\n            for i in range(len(q)):\n                r, c, k = q.popleft()\n\n                for x, y in direction:\n                    R = r + x\n                    C = c + y\n\n                    if R >= 0 and R < m and C >= 0 and C < n:\n                        if k > 0 and grid[R][C] == 1 and (R, C, k - 1) not in seen:\n                            q.append((R, C, k - 1))\n                            seen.add((R, C, k - 1))\n\n                        if grid[R][C] == 0 and (R, C, k) not in seen:\n                            if R == m - 1 and C == n - 1:\n                                return steps + 1\n                            q.append((R, C, k))\n                            seen.add((R, C, k))\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int: \n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n\n        queue = deque([(0,0,k,0)])\n        visited = set([(0,0,k)])\n\n        \n\n        while queue:\n            row, col, eliminate, steps = queue.popleft()\n            for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n                if (new_row >= 0 and\n                    new_row < len(grid) and\n                    new_col >= 0 and\n                    new_col < len(grid[0])):\n                    if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n                        visited.add((new_row, new_col, eliminate-1))\n                        queue.append((new_row, new_col, eliminate-1, steps+1))\n                    if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n                        if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n                            return steps+1\n                        visited.add((new_row, new_col, eliminate))\n                        queue.append((new_row, new_col, eliminate, steps+1))\n\n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        d = deque([(0,0,k)])\n        visited = {(0,0,k)}\n        def get_neigbour(x,y,z):\n            for x0, y0 in ((x-1,y), (x+1, y), (x, y-1), (x,y+1)):\n                if 0 <= x0 < m and 0 <= y0 < n:\n                    z0 = z - grid[x0][y0]\n                    if z0 >= 0:\n                        yield (x0, y0, z0)\n        steps = 0\n        \n        while d:\n            size = len(d)\n            for i in range(size):\n                x, y, z = d.popleft()\n                if (x,y) == (m-1, n-1):\n                    return steps\n                for nxt in get_neigbour(x, y, z):\n                    if nxt in visited:\n                        continue\n                    visited.add(nxt)\n                    d.append(nxt)\n            steps += 1\n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = deque()\n        cur = (0, 0, k, 0)\n        visited = set()\n        q.append(cur)\n        visited.add(cur)\n        m = len(grid)\n        n = len(grid[0])\n        \n        diffs = [(1,0),(-1,0),(0,1),(0,-1)]\n        \n        while len(q) != 0:\n            i, j, l, s = q.popleft()\n            # print(i, j)\n            if i == m-1 and j == n-1:\n                return s\n            \n            for d in diffs:\n                n_i = i + d[0]\n                n_j = j + d[1]\n                # print(\\\"n: \\\", n_i, n_j)\n                if 0 <= n_i < m and 0 <= n_j < n:\n                    if grid[n_i][n_j] and l != 0 and (n_i, n_j, l-1) not in visited:\n                        q.append((n_i, n_j, l-1, s+1))\n                        visited.add((n_i, n_j, l-1))\n                    elif not grid[n_i][n_j] and (n_i, n_j, l) not in visited:\n                        q.append((n_i, n_j, l, s+1))\n                        visited.add((n_i, n_j, l))\n                        \n        return -1\n                        \n                    \n                        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        r, c = len(grid), len(grid[0])\n        if r == 1 and c == 1:\n            return 0\n        q = deque([(0, 0, 0, 0)])    # row, col, num of obstables met, steps \n        visited = set((0, 0, 0))\n        \n        while q:\n            row, col, met, step = q.popleft()\n            if met > k:\n                continue\n            for nr, nc in [[row+1, col], [row-1, col], [row, col+1], [row, col-1]]:\n                if 0 <= nr < r and 0 <= nc < c:\n                    if grid[nr][nc] == 1 and met < k and (nr, nc, met+1) not in visited:\n                        visited.add((nr, nc, met+1))\n                        q.append((nr, nc, met+1, step+1))\n                    if grid[nr][nc] == 0 and (nr, nc, met) not in visited:\n                        if (nr, nc) == (r-1, c-1):\n                            return step + 1\n                        visited.add((nr, nc, met))\n                        q.append((nr, nc, met, step+1))\n                        \n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n = len(grid)\n        m = len(grid[0])\n        queue = [(0, 0, k)]\n        step = 0\n        ds = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n        visited = {(0, 0, k)}\n        if n == 1 and m == 1:\n            return 0\n        while queue:\n            # print(queue)\n            tmp = queue\n            queue = []\n            for i, j, eliminate in tmp:\n                for d in ds:\n                    x = i + d[0]\n                    y = j + d[1]\n                    if x == n - 1 and y == m - 1:\n                        return step + 1\n                    if x >= 0 and x < n and y >= 0 and y < m:\n                        if grid[x][y] == 0 and (x, y, eliminate) not in visited:\n                            visited.add((x, y, eliminate))\n                            queue.append((x, y, eliminate))\n                        elif grid[x][y] == 1 and eliminate >= 1 and (x, y, eliminate - 1) not in visited:\n                            visited.add((x, y, eliminate - 1))\n                            queue.append((x, y, eliminate - 1))\n            step += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid:\n            return 0\n        \n        queue = collections.deque([(0,0,k,0)])\n        r, c = len(grid), len(grid[0])\n        \n        visited = set()\n        direction = []\n        while queue:\n            x, y, eliminate, steps = queue.popleft()\n            if x == r-1 and y == c-1:\n                return steps\n            for nx, ny in (x+1, y), (x-1, y), (x, y-1), (x, y+1):\n                if nx >= 0 and nx < r and ny >= 0 and ny < c:\n                    if eliminate > 0 and (nx, ny, eliminate-1) not in visited and grid[nx][ny] == 1:\n                        queue.append((nx, ny, eliminate-1, steps+1))\n                        visited.add((nx, ny, eliminate-1))\n                    if (nx, ny, eliminate) not in visited and grid[nx][ny] == 0:\n                        queue.append((nx, ny, eliminate, steps+1))\n                        visited.add((nx, ny, eliminate))\n\n                    \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n,m = len(grid),len(grid[0])\n        # cost, used, i, j\n        bfs = collections.deque([(0,0,0,0)])\n        seen = set([(0,0,0)])\n        while bfs:\n            c,used,i,j = bfs.popleft()\n            if i==n-1 and j==m-1:\n                return c\n            for ni,nj in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                if 0<=ni<n and 0<=nj<m and used+grid[ni][nj]<=k and (ni,nj,used+grid[ni][nj]) not in seen:\n                    bfs.append((c+1,used+grid[ni][nj],ni,nj))\n                    seen.add((ni,nj,used+grid[ni][nj]))\n        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = collections.deque([(0, 0, 0, 0)])\n        m, n = len(grid), len(grid[0])\n        visited = set()\n         \n        while q:\n            x, y, obstacle, path = q.popleft()\n            for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n                if 0 <= i < m and 0 <= j < n:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n                        visited.add((i, j, obstacle + 1))\n                        q.append((i, j, obstacle + 1, path + 1))\n                    if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n                        if (i, j) == (m - 1, n - 1):\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        q.append((i, j, obstacle, path + 1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue=[(0,0,k)]\n        direction=[(1,0),(0,1),(-1,0),(0,-1)]\n        h=len(grid)\n        w=len(grid[0])\n        step=0\n        if h==1 and w==1:\n            return 0\n        visited={}\n        while queue:\n            target={}\n            step+=1\n            for y0,x0,r in queue:\n                for y_offset,x_offset in direction:\n                    y1=y0+y_offset\n                    x1=x0+x_offset\n                    if 0<=y1<h and 0<=x1<w:\n                        if y1==h-1 and x1==w-1:\n                            return step\n                        if (y1,x1) in visited:\n                            if visited[(y1,x1)]>=r:\n                                continue\n                        if grid[y1][x1]==0:\n                            visited[(y1,x1)]=r\n                            target[(y1,x1)]=max(target.get((y1,x1),r),r)\n                        else:\n                            if r>0:\n                                visited[(y1,x1)]=r-1\n                                target[(y1,x1)]=max(target.get((y1,x1),r-1),r-1)\n            queue=[(k[0],k[1],v) for k,v in target.items()]\n        return -1", "from collections import deque\ndirs = [(0, 1), (0, -1), (-1, 0), (1, 0)]\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        dq = deque([(0, 0, k)])\n        visited = set([(0, 0, k)])\n        step = 0\n        while dq:\n            size = len(dq)\n            for i in range(size):\n                r, c, o = dq.popleft() # o: remianing eliminate obstacle [o >= 0]\n                if r == m - 1 and c == n - 1:\n                    return step\n                for d in dirs:\n                    nr, nc = r + d[0], c + d[1]\n                    if not (0 <= nr < m) or not (0 <= nc < n):\n                        continue\n                    if grid[nr][nc] == 0:\n                        if (nr, nc, o) not in visited:\n                            dq.append((nr, nc, o))\n                            visited.add((nr, nc, o))\n                    elif grid[nr][nc] == 1:\n                        if o > 0 and (nr, nc, o - 1) not in visited:\n                            dq.append((nr, nc, o - 1))\n                            visited.add((nr, nc, o - 1))\n            step += 1\n        return -1\n                \n", "class Solution:\n    def shortestPath(self, grid, k):\n        if not grid or not grid[0]:\n            return -1\n        n = len(grid)\n        m = len(grid[0])\n        q = [[0, 0, 0, k]]  # len, row,col, obstacles is left\n        seen = set()\n        # use obstacle as part of state\n        seen.add((0, 0, k))\n        while q:\n            # consider [r,c]\n            d, r, c, ob = q.pop(0)\n            if r == n - 1 and c == m - 1:\n                return d\n            # if current pos is 1, reduce obstacle by 1\n            # if grid[r][c] == 1:\n            #     if ob == 0:\n            #         continue\n            #     ob -= 1\n            for dr, dc in [[0, 1], [1, 0], [0, -1], [-1, 0]]:\n                nr = r + dr\n                nc = c + dc\n                if 0 <= nr < n and 0 <= nc < m:\n                    new_ob = ob\n                    if grid[nr][nc] == 1:\n                        new_ob -= 1\n                        if new_ob < 0:\n                            continue\n                    if (nr, nc, new_ob) in seen:\n                        continue\n                    q.append([d + 1, nr, nc, new_ob])\n                    seen.add((nr, nc, new_ob))\n        return -1\n\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        visited = set()\n        \n        directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]\n        queue = [(0, 0, 0)]\n        steps = 0\n        \n        while queue:\n            new_q = []\n            for x, y, r in queue:\n                if x == len(grid) - 1 and y == len(grid[0]) - 1:\n                    return steps\n                for ix, iy in directions:\n                    xx = x + ix\n                    yy = y + iy\n                    if xx >= 0 and xx < len(grid) and yy >= 0 and yy < len(grid[0]):\n                        rr = r + (1 if grid[xx][yy] == 1 else 0)\n                        if (xx, yy, rr) not in visited and rr <= k:\n                            visited.add((xx, yy, rr))\n                            new_q.append((xx, yy, rr))\n            steps += 1\n            queue = new_q\n        \n        return -1\n                            \n                        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        r, c = len(grid), len(grid[0])\n        qu = deque([[0,0,0,0]])\n        visited = set()\n        while qu:\n            i,j,cnt,length = qu.popleft()\n            visited.add((i,j,cnt))\n            if (i,j) == (r-1,c-1): return length\n            for x, y in [[i-1,j],[i+1,j],[i,j-1],[i,j+1]]:\n                if 0<=x<r and 0<=y<c:\n                    new_cnt = cnt if grid[x][y] == 0 else cnt+1\n                    if new_cnt<=k and (x,y,new_cnt) not in visited:\n                        visited.add((x,y,new_cnt))\n                        qu.append([x,y,new_cnt,length+1])\n        return -1\n\n\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n        \n#         q = collections.deque([(0, 0, 0, 0)])\n#         m, n = len(grid), len(grid[0])\n#         visited = set()\n         \n#         while q:\n#             x, y, obstacle, path = q.popleft()\n#             for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n#                 if 0 <= i < m and 0 <= j < n:\n#                     if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n#                         visited.add((i, j, obstacle + 1))\n#                         q.append((i, j, obstacle + 1, path + 1))\n#                     if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n#                         if (i, j) == (m - 1, n - 1):\n#                             return path + 1\n#                         visited.add((i, j, obstacle))\n#                         q.append((i, j, obstacle, path + 1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        #BFS wth obstacle elimination\n        \n        #when should u add the visited?? eg. test case.   0 1 0 1\n                                                        # 0 0 1 0\n        \n        queue = []\n        queue.append((0,0,0,0)) #i,j,obstacles used, distance\n        visited = set()\n        visited.add((0,0,0)) #i, j, obstacles used\n        \n        while queue:\n            i,j,obstacles_used,length = queue.pop(0)\n            if i == len(grid)-1 and j == len(grid[0])-1:\n                return length #because of the stpid base case [[0]]\n\n            directions = [(1, 0),(-1,0),(0,1),(0,-1)]\n            for a,b in directions:\n                newi = i+a\n                newj = j+b\n                if newi >=0 and newi<len(grid) and newj>=0 and newj<len(grid[0]):   \n                    newObstacles = obstacles_used + grid[newi][newj]\n                    # if newi == len(grid)-1 and newj == len(grid[0])-1 and newObstacles <=k:\n                    #     return length + 1\n                    if newObstacles <=k and (newi, newj, newObstacles) not in visited:\n                        visited.add((newi, newj, newObstacles))\n                        queue.append((newi,newj, newObstacles, length+1))\n\n            \n        return -1\n            \n            \n        \n        \n        \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        q = collections.deque([(0,0,0,k)])\n        vis = set([(0,0,k)])\n        \n        while q:\n            \n            x,y,s,r = q.popleft()\n            if x == len(grid)-1 and y == len(grid[0])-1:\n                return s\n            \n            for i,j in [(x+1,y), (x,y+1), (x-1,y), (x,y-1)]:\n                \n                if 0 <= i < len(grid) and 0 <= j < len(grid[0]):\n                    \n                    if grid[i][j] == 1 and r > 0 and (i,j,r-1) not in vis:\n                        vis.add((i,j,r-1))\n                        q.append((i,j,s+1,r-1))\n                    \n                    if grid[i][j] == 0 and (i,j,r) not in vis:\n                        vis.add((i,j,r))\n                        q.append((i,j,s+1,r))\n            \n            \n        return -1", "from collections import defaultdict, deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def getNei(x,y):\n            for dx,dy in dirs:\n                xn,yn = x+dx,y+dy\n                if 0<=xn<M and 0<=yn<N:\n                    yield xn,yn\n                \n        dirs = [(1,0),(0,1),(-1,0),(0,-1)]\n        M, N = len(grid), len(grid[0])\n        inf_num = float(inf)\n        visited = [[[inf_num]*(k+1) for _ in range(N)] for _ in range(M)]\n        \n        # visited[0][0][k] = True\n        \n        queue = deque([(0,0,k,0)])\n        \n        while queue:\n            i, j, kk, cost = queue.popleft()\n            # print(i, j, kk, cost)\n            if i==M-1 and j==N-1:\n                return cost\n            \n            if visited[i][j][kk] < inf:\n                continue\n            visited[i][j][kk] = cost\n            \n            for x, y in getNei(i, j):\n                if grid[x][y] == 1:\n                    if kk > 0 and cost+1 < visited[x][y][kk]:\n                        queue.append((x, y, kk-1, cost+1))\n                else:\n                    if cost+1 < visited[x][y][kk]:\n                        queue.append((x, y, kk, cost+1))\n        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        visited={}\n        queue = deque()\n        queue.append([0,0])\n        visited[(0,0)] = 0\n        step = 0\n        offset = [(1,0),(-1,0),(0,1),(0,-1)]\n        while queue:\n            size = len(queue)\n            while size:\n                size -= 1  \n                x,y= queue.popleft()\n                obs = visited[(x, y)]\n                if x == m - 1 and y == n - 1:\n                    return step\n                \n                for dx, dy in offset:\n                    nx, ny = x + dx, y + dy                \n                    if  0<=nx<m and 0 <=ny <n and (nx, ny):              \n                        n_obs = obs + grid[nx][ny] \n                        if n_obs  > k:\n                            continue   \n                        if (nx, ny) in visited and n_obs < visited[(nx, ny)]:\n                            visited[(nx, ny)] = n_obs\n                            queue.append((nx, ny))\n                        elif (nx, ny) not in visited:                                \n                            visited[(nx, ny)] = n_obs\n                            queue.append((nx, ny))               \n                    \n            step += 1\n    \n              \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = []\n        q.append((0, 0, 0, 0))\n        m, n = len(grid), len(grid[0])\n        visited = set()\n        while q:\n            x, y, obstacle_eliminated, count = q.pop(0)\n            for nx, ny in  [(x-1, y),(x, y+1),(x+1, y),(x, y-1)]:\n                if 0 <= nx < m and 0 <= ny < n:\n                    if (nx, ny) == (m - 1, n - 1):\n                            return count + 1\n                    if grid[nx][ny] == 1 and obstacle_eliminated < k and (nx, ny, obstacle_eliminated + 1) not in visited:\n                        visited.add((nx, ny, obstacle_eliminated + 1))\n                        q.append((nx, ny, obstacle_eliminated + 1, count + 1))\n                    if grid[nx][ny] == 0 and (nx, ny, obstacle_eliminated) not in visited:    \n                        visited.add((nx, ny, obstacle_eliminated))\n                        q.append((nx, ny, obstacle_eliminated, count + 1))\n                        \n        return -1", "class Solution:\n    \\\"\\\"\\\"\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = collections.deque([(0,0,0)]) # row, col, num of obstacles met so far\n        visited = {(0,0): 0}           # row, col   =>   num of obstacles met so far\n        steps = 0\n        \n        while q:\n            for _ in range(len(q)):\n                i, j, obstacles = q.popleft()\n                \n                if obstacles > k:\n                    continue\n                \n                if i == len(grid)-1 and j == len(grid[0]) - 1:\n                    return steps\n                \n                neighbors = [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]\n                \n                for x, y in neighbors:\n                    if 0 <= x < len(grid) and 0 <= y < len(grid[0]):\n                        next_obstacle = obstacles + grid[x][y]\n                        \n                        if next_obstacle < visited.get((x,y), float(\\\"inf\\\")):\n                            visited[(x,y)] = next_obstacle\n                            q.append((x, y, next_obstacle))\n            steps += 1\n        return -1\n    \\\"\\\"\\\"\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = collections.deque([(0,0,0,0)]) # row, col, obstacles_removed, distance_from_origin\n        visited = {(0, 0, 0)}              # row, col, obstacles_removed\n        \n        while q:\n            i, j, obstacles, dist = q.popleft()\n            \n            if i == len(grid)-1 and j == len(grid[0]) - 1:\n                return dist\n            \n            if obstacles > k:\n                continue\n            \n            neighbors = [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]\n            \n            for x, y in neighbors:\n                if 0 <= x < len(grid) and 0 <= y < len(grid[0]):\n                    if (x, y, obstacles + grid[x][y]) not in visited:\n                        visited.add((x, y, obstacles + grid[x][y]))\n                        q.append((x, y, obstacles + grid[x][y], dist + 1))\n                    \n                    # if grid[x][y] == 1:\n                    #     if obstacles < k and (x, y, obstacles+1) not in visited:\n                    #         visited.add((x, y, obstacles+1))\n                    #         q.append((x, y, obstacles+1, dist+1))\n                    # else:\n                    #     if (x, y, obstacles) not in visited:\n                    #         visited.add((x, y, obstacles))\n                    #         q.append((x, y, obstacles, dist+1))\n        return -1\n", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # if grid[0][0] == 1 and k == 0:\n        #     return -1\n        # m, n = len(grid), len(grid[0])\n        # a = k if grid[0][0] == 0 else k-1\n        # q = collections.deque([(0, 0, 0, a)])\n        # visited = set()\n        # visited.add((0,0,a))\n        # while q:\n        #     i, j, step, available = q.popleft()\n        #     if i == m-1 and j == n-1:\n        #         return step\n        #     for ni, nj in [[i+1, j], [i-1, j], [i, j+1], [i, j-1]]:\n        #         if ni < 0 or ni >= m or nj < 0 or nj >= n:\n        #             continue\n        #         if grid[ni][nj] == 1 and not available:\n        #             continue\n        #         if (ni, nj, available) not in visited:\n        #             visited.add((ni, nj, available))\n        #             if grid[ni][nj] == 0:\n        #                 q.append([ni, nj, step+1, available])\n        #             if grid[ni][nj] == 1:\n        #                 if available:\n        #                     q.append([ni, nj, step+1, available-1])                                    \n        # return -1\n        if grid[0][0] == 1:\n            k -= 1\n            \n        q = deque([(0,0,k,0)])\n        visited = set([(0,0,k)])\n        \n        while len(q) > 0:\n            r, c, avail, path = q.popleft()\n            if r == len(grid)-1 and c == len(grid[0])-1:\n                return path\n            \n            for dr, dc in [(0,1), (0,-1), (1,0), (-1,0)]:\n                nr, nc = r+dr, c+dc\n                \n                if nr < 0 or nr >= len(grid) or nc < 0 or nc >= len(grid[0]):\n                    continue\n                    \n                if grid[nr][nc] == 1 and not avail:\n                    continue\n                \n                if (nr, nc, avail) in visited:\n                    continue\n                \n                visited.add((nr, nc, avail))\n                if grid[nr][nc] == 0:\n                    q.append((nr, nc, avail, path+1))\n                elif avail > 0:\n                    q.append((nr, nc, avail-1, path+1))\n        \n        return -1\n\n                \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        q = collections.deque([(0,0,0,k)])\n        vis = set([(0,0,k)])\n        \n        while q:\n            \n            x,y,s,r = q.popleft()\n            if x == len(grid)-1 and y == len(grid[0])-1:\n                return s\n            \n            for i,j in [(x+1,y), (x,y+1), (x-1,y), (x,y-1)]:\n                \n                if 0 <= i < len(grid) and 0 <= j < len(grid[0]):\n                    # if i == len(grid)-1 and y == len(grid[0])-1:\n                        # return s+1\n                    \n                    if grid[i][j] == 1 and r > 0 and (i,j,r-1) not in vis:\n                        vis.add((i,j,r-1))\n                        q.append((i,j,s+1,r-1))\n                    \n                    if grid[i][j] == 0 and (i,j,r) not in vis:\n                        vis.add((i,j,r))\n                        q.append((i,j,s+1,r))\n            \n            \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        if len(grid[0]) == 1 and len(grid) == 1:\n            return 0\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            for i, j in directions:\n                nr = row + i\n                nc = col + j\n                d = dist + 1\n                if nr < len(grid) and nr >= 0 and nc < len(grid[0]) and nc >= 0: \n                    if (nr, nc, cur_k) not in visited and grid[nr][nc] == 0:\n                        if nr == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                            return dist + 1\n                        q.append((nr, col+j, d, cur_k))\n                        visited.add((nr, col+j, cur_k))\n                    if (nr, nc, cur_k-1) not in visited and grid[nr][nc] == 1:\n                        if cur_k > 0:\n                            if nr == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                                return dist + 1\n                            q.append((nr, nc, d, cur_k-1))\n                            visited.add((nr, nc, cur_k-1))\n        return -1\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "from collections import deque\n\n\n# class Node:\n#     def __init__(self, row, col):\n#         self.row = row\n#         self.col = col\n#         self.k_used = 0\n#         self.steps_taken = -1\n#         self.discovered = False\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1: #if only one node then we don't need to move\n            return 0\n        \n        queue = deque([(0,0,k,0)])\n        visited = set([(0,0,k)])\n        \n        #why do we need 2 separate queues?\n        \n        while queue:\n            row, col, eliminate, steps = queue.popleft()\n            for new_row, new_col in [(row-1, col), (row, col+1), (row+1, col), (row, col-1)]: #clean way to handle long if statement\n                if (new_row >= 0 and new_row < len(grid) and new_col >= 0 and new_col < len(grid[0])):\n                    if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n                        visited.add((new_row, new_col, eliminate-1))\n                        queue.append((new_row, new_col, eliminate-1, steps+1))\n                    if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n                        if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n                            return steps+1\n                        visited.add((new_row, new_col, eliminate))\n                        queue.append((new_row, new_col, eliminate, steps+1))\n                        \n        return -1\n        \n        \n        \n# grid = \n# [[0,0,0],\n#  [1,1,0],\n#  [0,0,0],\n#  [0,1,1],\n#  [0,0,0]],\n\n#breadth first search to find distance of each node from upper left\n#keep track of number of obstacles eliminated\n#if num of obstacles eliminated == k or reached ending, then that node has no edges\n\n#question: do we need to revisit a node we reached before? yes if k < prev_k when we previously reached that node\n\n#what do we store in the bfs search? indices, k, dist, steps from upper left\n#how to remember that we traversed a node? #initialize this \n\n#         grid_info = []\n#         for row in range(len(grid)):\n#             grid_info.append([])\n#             for col in range(len(grid[0])): #assume we have at least 1 row\n#                 grid_info[row].append(Node(row, col))\n                \n#         grid_info[0][0].steps_taken = 0\n#         grid_info[0][0].discovered = True\n\n#         queue = deque([grid_info[0][0]]) #assume we don't start at obstacle\n#         while len(queue) > 0:\n#             cur_node = queue.popleft()\n#             if cur_node.row > 0:\n#                 up_node = grid_info[cur_node.row - 1][cur_node.col]\n#                 self.check_and_add_to_queue(queue, cur_node, up_node, k, grid)\n#             if cur_node.row < len(grid) - 1:\n#                 down_node = grid_info[cur_node.row + 1][cur_node.col]\n#                 self.check_and_add_to_queue(queue, cur_node, down_node, k, grid)\n#             if cur_node.col > 0:\n#                 left_node = grid_info[cur_node.row][cur_node.col - 1]\n#                 self.check_and_add_to_queue(queue, cur_node, left_node, k, grid)\n#             if cur_node.col < len(grid[0]) - 1:\n#                 right_node = grid_info[cur_node.row][cur_node.col + 1]\n#                 self.check_and_add_to_queue(queue, cur_node, right_node, k, grid)\n        \n#         return grid_info[len(grid) - 1][len(grid[0]) -1 ].steps_taken\n                \n#     def check_and_add_to_queue(self, queue, cur_node, new_node, k, grid):\n#         if (not new_node.discovered and ((grid[new_node.row][new_node.col] == 0 and cur_node.k_used <= k) or (grid[new_node.row][new_node.col] == 1 and cur_node.k_used + 1 <= k))) or (grid[new_node.row][new_node.col] == 0 and cur_node.k_used < new_node.k_used) or grid[new_node.row][new_node.col] == 1 and cur_node.k_used + 1 < new_node.k_used:\n#             queue.append(new_node)\n#             new_node.discovered = True\n#             if grid[new_node.row][new_node.col] == 1:\n#                 new_node.k_used = cur_node.k_used + 1\n#             else:\n#                 new_node.k_used = cur_node.k_used\n#             new_node.steps_taken = cur_node.steps_taken + 1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or grid[0][0]==1 or grid[-1][-1]==1:\n            return -1\n        r,c=len(grid),len(grid[0])\n        dirs=[(0,1),(0,-1),(1,0),(-1,0)]\n        visited=set()\n        q=[(0,0,0,k)]\n        visited.add((0,0,0))\n        while q:\n            x,y,steps,obs=q.pop(0)\n            if obs<0:\n                continue\n            if x==r-1 and y==c-1:\n                return steps\n            for dx,dy in dirs:\n                nx,ny=x+dx,y+dy\n                if 0<=nx<r and 0<=ny<c and grid[nx][ny]==0:\n                    if (nx,ny,obs) not in visited:\n                        q.append((nx,ny,steps+1,obs))\n                        visited.add((nx,ny,obs))\n                elif 0<=nx<r and 0<=ny<c and grid[nx][ny]==1:   \n                    if obs>0:\n                        if (nx,ny,obs-1) not in visited:\n                            q.append((nx,ny,steps+1,obs-1))\n                            visited.add((nx,ny,obs-1))  \n        return -1                 ", "from typing import List\nfrom functools import lru_cache\nimport collections\nimport heapq\nimport itertools\nimport bisect\nimport copy\nimport random\nimport re\nimport fractions\nimport math\nimport functools\n\nmod = 10 ** 9 + 7\n\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not len(grid) or not len(grid[0]):\n            return 0\n        m, n = len(grid), len(grid[0])\n\n\n        def neighbors(i, j):\n            for ni, nj in ((i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)):\n                if 0 <= ni < m and 0 <= nj < n:\n                    yield ni, nj\n\n        start = (0, 0, k)\n        seen = {start}\n        q = collections.deque([(0, start)])\n        while q:\n            step, (i, j, k) = q.popleft()\n            # if k >= (m - i - 1) + (n - j - 1) - 1:\n                # return step + (m - i - 1) + (n - j - 1)\n            if (i, j) == (m - 1, n - 1):\n                return step\n            for ni, nj in neighbors(i, j):\n                nk = k - grid[ni][nj]\n                state = (ni, nj, nk)\n                if nk >= 0 and state not in seen:\n                    q.append((step + 1, state))\n                    seen.add(state)\n\n        return -1\n\n", "class Solution:\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n    \n        length, width = len(grid), len(grid[0])\n        # (l,w,steps,k)\n        que = collections.deque([])\n        que.append((0,0,0,k))\n        visited = set()\n        visited.add((0,0,k))\n        directions = ([-1,0],[0,1],[1,0],[0,-1])\n        while len(que):\n            x,y,steps,eliminates = que.popleft()\n            # BFS \u4fdd\u8bc1\u7b2c\u4e00\u4e2avisit\u662fsteps\u6700\u5c11\u7684\n            if x == length-1 and y == width-1:\n                return steps\n            for dx, dy in directions:\n                next_x = x + dx\n                next_y = y + dy\n                if self.isValid(next_x,next_y,grid) and (next_x,next_y,eliminates) not in visited:\n                    if grid[next_x][next_y] == 1 and eliminates > 0:\n                        visited.add((next_x,next_y,eliminates))\n                        que.append((next_x,next_y,steps+1,eliminates-1))\n                    elif grid[next_x][next_y] == 0:\n                        visited.add((next_x,next_y,eliminates))\n                        que.append((next_x,next_y,steps+1,eliminates))\n        return -1\n    \n    def isValid(self, next_x, next_y, grid):\n        if next_x >= 0 and next_x < len(grid) and next_y >= 0 and next_y <len(grid[0]):\n            return True\n        else:\n            return False", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def method1():\n            R=len(grid)\n            if R<1:\n                return -1\n            C=len(grid[0])\n            seen=set()\n            queue=collections.deque([(0,0,k,0)]) #r,c,k,dist\n            seen.add((0,0,k))\n            \n            def neighbors(r,c):\n                for dr,dc in [(-1,0),(1,0),(0,-1),(0,1)]:\n                    nr,nc=r+dr,c+dc\n                    if (0<=nr<R and 0<=nc<C):\n                        yield nr,nc\n            \n            while queue:\n                r,c,ck,dist=queue.popleft()\n                if r==R-1 and c==C-1:\n                    return dist\n                \n                for nr,nc in neighbors(r,c):\n                    newk=ck\n                    if grid[nr][nc]==1:\n                        newk-=1\n                        if newk<0:\n                            continue\n                    if (nr,nc,newk) in seen:\n                        continue\n                    seen.add((nr,nc,newk))\n                    queue.append((nr,nc,newk,dist+1)) \n                        \n            return -1\n        return method1()", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = set()\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and (ii, jj, k) not in seen:\n                            seen.add((ii, jj, k))\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and (ii, jj, k-1) not in seen:\n                            seen.add((ii, jj, k-1))\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = {}\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and ((ii, jj) not in seen or k > seen[(ii, jj)]):\n                            seen[(ii, jj)] = k\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and ((ii, jj) not in seen or k-1 > seen[(ii, jj)]):\n                            seen[(ii, jj)] = k-1\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q1, q2 = {}, {}\n        q1[(0, 0)] = 0\n        q2[(m-1, n-1)] = 0\n        level = 0\n        seen1, seen2 = {}, {}\n        seen1[(0, 0)] = 0\n        seen2[(m-1, n-1)] = 0\n        \n        while q1 and q2:\n            tmp = {}\n            if len(q2) < len(q1):\n                q1, q2 = q2, q1\n                seen1, seen2 = seen2, seen1\n            for (i, j), k in q1.items():\n                if (i, j) in q2 and k+q2[(i, j)] <= K:\n                    return level\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and ((ii, jj) not in seen1 or k < seen1[(ii, jj)]):\n                            seen1[(ii, jj)] = k\n                            tmp[(ii, jj)] = k\n                        if grid[ii][jj] == 1 and k < K and ((ii, jj) not in seen1 or k+1 < seen1[(ii, jj)]):\n                            seen1[(ii, jj)] = k+1\n                            tmp[(ii, jj)] = k+1\n            q1 = tmp\n            level += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def method1():\n            R=len(grid)\n            if R<1:\n                return -1\n            C=len(grid[0])\n            seen=set()\n            queue=collections.deque([(0,0,k,0)]) #r,c,k,dist\n            seen.add((0,0,k))\n            \n            def neighbors(r,c):\n                for dr,dc in [(-1,0),(1,0),(0,-1),(0,1)]:\n                    nr,nc=r+dr,c+dc\n                    if (0<=nr<R and 0<=nc<C):\n                        yield nr,nc\n            \n            while queue:\n                r,c,K,dist=queue.popleft()\n                if r==R-1 and c==C-1:\n                    return dist\n                \n                for nr,nc in neighbors(r,c):\n                    if grid[nr][nc]==1:\n                        if K==0:\n                            continue\n                        if (nr,nc,K-1) in seen:\n                            continue\n                        seen.add((nr,nc,K-1))\n                        queue.append((nr,nc,K-1,dist+1)) \n                    else:\n                        if (nr,nc,K) in seen:\n                            continue  \n                        seen.add((nr,nc,K))\n                        queue.append((nr,nc,K,dist+1))\n                        \n            return -1\n        return method1()", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        if len(grid[0]) == 1 and len(grid) == 1:\n            return 0\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            for nr, nc in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n                d = dist + 1\n                if nr < len(grid) and nr >= 0 and nc < len(grid[0]) and nc >= 0: \n                    if (nr, nc, cur_k) not in visited and grid[nr][nc] == 0:\n                        if nr == len(grid) - 1 and nc == len(grid[0]) - 1:\n                            return dist + 1\n                        q.append((nr, nc, d, cur_k))\n                        visited.add((nr, nc, cur_k))\n                    if (nr, nc, cur_k-1) not in visited and grid[nr][nc] == 1:\n                        if cur_k > 0:\n                            if nr == len(grid) - 1 and nc == len(grid[0]) - 1:\n                                return dist + 1\n                            q.append((nr, nc, d, cur_k-1))\n                            visited.add((nr, nc, cur_k-1))\n        return -1\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def method1():\n            R=len(grid)\n            if R<1:\n                return -1\n            C=len(grid[0])\n            seen=set()\n            queue=collections.deque([(0,0,k,0)]) #r,c,k,dist\n            seen.add((0,0,k))\n            \n            def neighbors(r,c):\n                for dr,dc in [(-1,0),(1,0),(0,-1),(0,1)]:\n                    nr,nc=r+dr,c+dc\n                    if (0<=nr<R and 0<=nc<C):\n                        yield nr,nc\n            \n            while queue:\n                r,c,K,dist=queue.popleft()\n                if r==R-1 and c==C-1:\n                    return dist\n                \n                for nr,nc in neighbors(r,c):\n                    KK=K\n                    if grid[nr][nc]==1:\n                        KK=KK-1\n                        if KK<0:\n                            continue\n                    if (nr,nc,KK) in seen:\n                        continue\n                    seen.add((nr,nc,KK))\n                    queue.append((nr,nc,KK,dist+1)) \n                        \n            return -1\n        return method1()", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = collections.deque([(0, 0, k)])\n        m, n = len(grid), len(grid[0])\n        step = 0\n        visited = set()\n        while q:\n            nq = collections.deque()\n            \n            while q:\n                x, y, curk = q.popleft()\n                visited.add((x,y, curk))\n                if x == m-1 and y == n-1:\n                    return step\n                for dx, dy in [[-1, 0], [1, 0], [0, -1], [0, 1]]:\n                    nx = x + dx\n                    ny = y + dy\n\n                    if not (0 <= nx < m and 0 <= ny < n):\n                        continue\n                    if grid[nx][ny] == 1 and curk-1>=0 and (nx, ny, curk-1) not in visited:\n                        nq.append((nx, ny, curk-1))\n                        visited.add((nx,ny,curk-1))\n                    elif grid[nx][ny] == 0 and (nx, ny, curk) not in visited:\n                        nq.append((nx,ny,curk))\n                        visited.add((nx,ny,curk))\n                    # if grid[nx][ny] == 0:\n                    #     if (nx, ny, curk) not in visited:\n                    #         # visited.add((nx, ny, curk))\n                    #         nq.append((nx, ny, curk))\n                    # elif curk > 0:\n                    #     if (nx, ny, curk) not in visited:\n                    #         # visited.add((nx, ny, curk))\n                    #         nq.append((nx, ny, curk-1))\n            # print(nq)\n            step += 1\n            q = nq\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = collections.deque([(0,0,k,0)])\n        h = len(grid)\n        if h==0:\n            return 0\n        w = len(grid[0])\n        visited = set()\n        while len(queue) > 0:\n            i,j,k_left,step = queue.popleft()\n            if i<0 or j<0 or i>=h or j>=w: # in valid\n                continue\n            if grid[i][j] == 1:\n                k_left -= 1    \n            # print(i,j,k_left)\n            if k_left < 0 or (i,j,k_left) in visited:\n                continue\n            \n            visited.add((i,j,k_left))\n            # print(\\\"visit\\\",i,j,\\\"   k\\\",k_left,\\\"step\\\",step)\n\n            if i == h-1 and j== w-1:\n                return step\n            \n            queue.append((i+1,j,k_left,step+1))\n            queue.append((i-1,j,k_left,step+1))\n            queue.append((i,j+1,k_left,step+1))\n            queue.append((i,j-1,k_left,step+1))\n                \n        return -1\n        \n        \n        \n", "from collections import deque\nfrom typing import List\n\nclass Solution:\n    def getNeighbors(self, width, height, node):\n        row, column = node\n        \n        for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:\n            rr, cc = row + dr, column + dc\n            \n            if 0 <= rr < height and 0 <= cc < width:\n                yield (rr, cc)\n\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        height, width = len(grid), len(grid[0])\n        \n        queue = deque()\n        queue.append(((0, 0), k))\n        \n        result, visited = 0, set()\n        visited.add(((0, 0), k))\n\n        while queue:\n            length = len(queue)\n            \n            for _ in range(length):\n                (node, remove_capacity) = queue.popleft()\n            \n                if node == (height-1, width-1):\n                    return result\n    \n                for (rr, cc) in self.getNeighbors(width, height, node):\n                    capacity = remove_capacity - grid[rr][cc]\n                    key = ((rr, cc), capacity)\n\n                    if key not in visited and capacity >= 0:\n                        queue.append(key)\n                        visited.add(key)\n            \n            result += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        innerQueue = deque()\n        innerQueue.append((0,0,0,0))\n        \n        gridSet = set()  # i, j, obstacle\n        gridSet.add((0,0,0))\n        directions = [[-1,0], [0, -1], [1,0], [0, 1]]\n        ans = -1\n            \n        while len(innerQueue) > 0:\n            i, j, obstacle, distance = innerQueue.popleft()\n            if i == len(grid) -1 and j == len(grid[0]) - 1:\n                ans = distance\n                return ans\n            \n            for direction in directions:\n                ni = i + direction[0]\n                nj = j + direction[1]\n                \n                if ni >= 0 and nj >= 0 and ni <len(grid) and nj < len(grid[0]):\n                    if grid[ni][nj] == 1 and (ni, nj, obstacle + 1) not in gridSet and obstacle + 1 <= k:\n                        gridSet.add((ni, nj, obstacle + 1))\n                        innerQueue.append((ni, nj, obstacle + 1, distance + 1))\n                    elif grid[ni][nj]== 0 and (ni, nj, obstacle) not in gridSet:\n                        gridSet.add((ni, nj, obstacle))\n                        innerQueue.append((ni, nj, obstacle, distance + 1))\n            \n            \n        \n        return ans", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid)==1 and len(grid[0]) == 1:\n            return 0\n        q = collections.deque()\n        visited = set((0,0,0))\n        q.append(((0,0),0))\n        level = 1\n        while(len(q)>0):\n            length = len(q)\n            for i in range(length):\n                curr = q.popleft()\n                for dx,dy in [(-1,0),(1,0),(0,-1),(0,1)]:\n                    new_x = curr[0][0]+dx\n                    new_y = curr[0][1]+dy\n                    if new_x>=0 and new_x<len(grid) and new_y>=0 and new_y<len(grid[0]):\n                        obs = curr[1]\n                        if grid[new_x][new_y] == 1:\n                            obs+=1\n                        if (new_x,new_y,obs) not in visited and obs<=k:\n                                visited.add((new_x,new_y, obs))\n                                q.append(((new_x,new_y),obs))\n                                if new_x == len(grid)-1 and new_y == len(grid[0])-1:\n                                    return level\n            level+=1\n        return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return -1\n\n        def boundary_check(r, c):\n            return 0 <= r < len(grid) and 0 <= c < len(grid[0])\n\n        q = deque([((0, 0, k), 0)])\n        visited = set((0, 0, k))\n        directions = ((0, 1), (0, -1), (1, 0), (-1, 0))\n        end_cell = (len(grid)-1, len(grid[0])-1)\n\n        while q:\n            (r, c, obst_rem), jumps = q.popleft()\n            if (r, c) == end_cell:\n                return jumps\n\n            for x, y in directions:\n                nxt_r, nxt_c = r + x, c + y\n                if boundary_check(nxt_r, nxt_c):\n                    if grid[nxt_r][nxt_c] == 0:\n                        nxt_state = (nxt_r, nxt_c, obst_rem)\n                    elif obst_rem > 0:\n                        nxt_state = (nxt_r, nxt_c, obst_rem-1)\n                    else:\n                        continue\n                    if nxt_state not in visited:\n                        visited.add(nxt_state)\n                        q.append((nxt_state, jumps+1))\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q, d = deque([(0,0)]), {(0,0):(0,0)}\n        while q:\n            i,j = q.popleft()\n            dist, obst = d[(i,j)]\n            for m,n in [(i-1,j),(i,j-1),(i+1,j),(i,j+1)]:\n                if 0<=m<len(grid) and 0<=n<len(grid[0]):\n                    if obst+grid[m][n] < d.get((m,n),(0,float('inf')))[1]:\n                        d[(m,n)] = (dist+1, obst+grid[m][n])\n                        q.append((m,n))\n            dist, obst = d.get((len(grid)-1,len(grid[0])-1), (0,float('inf')))\n            if obst <= k:\n                return dist\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        dp = [[[float('inf')] * (k + 1) for _ in range(n)] for _ in range(m)]\n        dp[0][0][k] = 0\n        q = deque([(0, 0, k)])\n        def move(i, j, k):\n            for di, dj in ((-1, 0), (1, 0), (0, -1), (0, 1)):\n                ni, nj = i + di, j + dj\n                if 0 <= ni < m and 0 <= nj < n and k >= grid[ni][nj]:\n                    yield ni, nj, k - grid[ni][nj]\n        while q:\n            i, j, k = q.pop()\n            if i == m - 1 and j == n - 1:\n                return dp[i][j][k]\n            \n            for ni, nj, nk in move(i, j, k):\n                if dp[i][j][k] + 1 < dp[ni][nj][nk]:\n                    dp[ni][nj][nk] = dp[i][j][k] + 1\n                    q.appendleft((ni, nj, nk))\n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        r, c = len(grid), len(grid[0])\n        if r == 1 and c == 1:\n            return 0\n        q = deque([(0, 0, 0, 0)])    # row, col, num of obstables met, steps \n        visited = set((0, 0, 0))\n        \n        while q:\n            row, col, met, step = q.popleft()\n            if met > k:\n                continue\n            for nr, nc in [[row+1, col], [row-1, col], [row, col+1], [row, col-1]]:\n                if 0 <= nr < r and 0 <= nc < c:\n                    if grid[nr][nc] == 1 and (nr, nc, met+1) not in visited:\n                        visited.add((nr, nc, met+1))\n                        q.append((nr, nc, met+1, step+1))\n                    if grid[nr][nc] == 0 and (nr, nc, met) not in visited:\n                        if nr == r-1 and nc == c-1:\n                            return step + 1\n                        visited.add((nr, nc, met))\n                        q.append((nr, nc, met, step+1))\n                        \n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        \n        # implies start == end\n        if m == 1 and n == 1:\n            return 0\n        \n        parent = {}\n        start = (0, 0, k)\n        goal = (m - 1, n - 1)\n        parent[start] = None\n        \n        k_left = -1\n        frontier = deque([start])\n        while len(frontier) > 0:\n            x, y, z = frontier.popleft()\n            if (goal[0], goal[1], k_left) in parent:\n                break\n            \n            for i, j in [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]:\n                if min(i, j) < 0 or i >= m or j >= n:\n                    continue\n                \n                if grid[i][j] == 0 and (i, j, z) not in parent:\n                    parent[(i, j, z)] = (x, y, z) \n                    frontier.append((i, j, z))\n                    if (i, j) == goal:\n                        k_left = z\n                        break\n\n                elif grid[i][j] == 1 and z > 0 and (i, j, z-1) not in parent:\n                    parent[(i, j, z-1)] = (x, y, z)\n                    frontier.append((i, j, z-1))\n                    if (i, j) == goal:\n                        k_left = z-1\n                        break\n        \n        current = (goal[0], goal[1], k_left)\n        steps = 0\n        if current not in parent:\n            return -1\n        while parent[current] is not None:\n            steps += 1\n            current = parent[current]\n        return steps\n                \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        visited = set()\n        def bfs(steps, x,y, oc):\n            visited.add((x,y, oc))\n            q = collections.deque()\n            q.append((steps, x, y, oc))\n            while q:\n                (steps, r,c, obstacleCount ) = q.popleft()\n                if r == m-1 and c == n-1:\n                    return steps\n                # neighbors = getneighbors(r,c, obstacleCount)\n                for (i,j, oc) in getneighbors(r,c, obstacleCount):\n                    if (i,j,oc) not in visited:\n                        visited.add((i,j,oc))\n                        q.append((steps+1, i,j, oc))\n            return -1\n                           \n        def getneighbors(x,y, oc):\n            result = []\n            for (x,y) in [(x+1, y), (x-1, y),(x, y+1), (x, y-1)]:\n                if 0 <= x < m and 0 <= y < n:\n                    newoc = oc + grid[x][y]\n                    if grid[x][y] == 0 or (grid[x][y] == 1 and newoc <=k ):\n                        # result.append((x,y, newoc))\n                        yield (x,y, newoc)\n                    \n            return result\n        return bfs(0, 0, 0, 0) #steps, i, j, obstacleCount\n        \n                \n                        \n                    \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if(len(grid) == 0):\n            return 0\n        m = len(grid)\n        n = len(grid[0])\n        visited = set()\n        directions = [(1,0),(0,1),(-1,0),(0,-1)]\n        visited.add((0,0,0))\n        queue = [(0,0,0,0)]\n        while(queue):\n            lvl, out, x,y = queue.pop(0)\n            if(x == m-1 and y== n-1):\n                return lvl\n            for dx,dy in directions:\n                if(x+dx<0 or y+dy<0 or x+dx>=m or y+dy>=n):\n                    continue\n                if(grid[x+dx][y+dy] == 0 and (out,x+dx,y+dy) not in  visited):\n                    visited.add((out,x+dx,y+dy))\n                    queue.append((lvl+1, out,x+dx,y+dy))\n                if(grid[x+dx][y+dy] == 1 and out < k and (out+1,x+dx,y+dy) not in visited):\n                    visited.add((out+1,x+dx,y+dy))\n                    queue.append((lvl+1, out+1,x+dx,y+dy))\n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        if len(grid[0]) == 1 and len(grid) == 1:\n            return 0\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            for i, j in directions:\n                nr = row + i\n                nc = col + j\n                if nr < len(grid) and nr >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (nr, col+j, cur_k) not in visited and grid[nr][col+j] == 0:\n                        if nr == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                            return dist + 1\n                        q.append((nr, col+j, dist+1, cur_k))\n                        visited.add((nr, col+j, cur_k))\n                    if (nr, col+j, cur_k-1) not in visited and grid[nr][col+j] == 1:\n                        if cur_k > 0:\n                            if nr == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                                return dist + 1\n                            q.append((nr, col+j, dist+1, cur_k-1))\n                            visited.add((nr, col+j, cur_k-1))\n        return -1\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        queue = collections.deque()\n        queue.append((0, 0, 0, k)) #i, j, level, k\n        dirs = ((-1, 0), (1, 0), (0, -1), (0, 1))\n        # visited = set([(0, 0, k)])\n        visited = set()\n        \n        while queue:\n            x, y, level, k = queue.popleft()\n            if x == m - 1 and y == n - 1:\n                return level\n            if (x, y, k) in visited:\n                continue\n            visited.add((x, y, k))\n            for dx, dy in dirs:\n                xx = x + dx\n                yy = y + dy\n                if  xx < 0 or xx >= m or yy < 0 or yy >= n:\n                    continue\n                if grid[xx][yy] == 0:\n                    # if (xx, yy, k) not in visited:\n                    queue.append((xx, yy, level+1, k))\n                        # visited.add((xx, yy, k))\n                else:\n                    if k > 0:\n                        # if (xx, yy, k-1) not in visited:\n                        queue.append((xx, yy, level+1, k-1))\n                            # visited.add((xx, yy, k-1))\n        return -1", "import collections\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # (x, y, steps, remaining k)\n        stack = collections.deque([(0, 0, 0, k)])\n        visited = set()\n        m = len(grid)-1\n        n = len(grid[0])-1\n        \n        while stack:\n            curr_x, curr_y, steps, remaining = stack.popleft()\n            if curr_x ==m and curr_y ==n:\n                return steps\n            if (curr_x, curr_y, remaining) in visited:\n                continue\n            visited.add((curr_x, curr_y, remaining))\n            directions = [(0, 1), (0, -1), (1, 0), (-1,0)]\n            for i, j in directions:\n                next_x = curr_x + i\n                next_y = curr_y +j\n                if next_x>=0 and next_y>=0 and next_x<=m and next_y <=n:\n                    if grid[next_x ][next_y] == 0 and (next_x, next_y, remaining) not in visited:\n                        stack.append((next_x, next_y, steps+1, remaining))\n                    elif remaining-1>=0 and (next_x, next_y, remaining-1) not in visited:\n                        stack.append((next_x ,next_y , steps+1, remaining-1))\n        return -1\n\n                \n            \n            \n            \n        \n    \n    \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if(len(grid) == 0):\n            return 0\n        m = len(grid)\n        n = len(grid[0])\n        if(m-1 == 0 and n-1 == 0 and grid[0][0] == 0):\n            return 0\n        visited = set()\n        directions = [(1,0),(0,1),(-1,0),(0,-1)]\n        visited.add((0,0,0))\n        queue = [(0,0,0,0)]\n        while(queue):\n            lvl, out, x,y = queue.pop(0)\n            for dx,dy in directions:\n                if(x+dx<0 or y+dy<0 or x+dx>=m or y+dy>=n):\n                    continue\n                if(x+dx == m-1 and y+dy == n-1):\n                    return lvl+1\n                if(grid[x+dx][y+dy] == 0 and (out,x+dx,y+dy) not in  visited):\n                    visited.add((out,x+dx,y+dy))\n                    queue.append((lvl+1, out,x+dx,y+dy))\n                if(grid[x+dx][y+dy] == 1 and out < k and (out+1,x+dx,y+dy) not in visited):\n                    visited.add((out+1,x+dx,y+dy))\n                    queue.append((lvl+1, out+1,x+dx,y+dy))\n        return -1", "class valWrapper:\n    def __init__(self, val, ind):\n        self.val = val\n        self.ind = ind\n\nclass Heap:\n    def __init__(self, maxsize):\n        self.size = 0\n        self.heap = [None for i in range(maxsize)]\n        self.ptr = {}\n    \n    def insert(self, key, val):\n        ind = self.size\n        v = valWrapper(val, ind)\n        self.heap[ind] = v\n        self.ptr[key] = v\n        self.size += 1\n        while(ind > 0 and self.heap[(ind-1)//2].val > self.heap[ind].val):\n            self.heap[(ind-1)//2].ind, self.heap[ind].ind = ind, (ind-1)//2\n            self.heap[(ind-1)//2], self.heap[ind] = self.heap[ind], self.heap[(ind-1)//2]\n    \n    def decrease_key(self, key, dec):\n        self.ptr[key].val -= dec\n        ind = self.ptr[key].ind\n        while(ind > 0 and self.heap[(ind-1)//2].val > self.heap[ind].val):\n            self.heap[(ind-1)//2].ind, self.heap[ind].ind = ind, (ind-1)//2\n            self.heap[(ind-1)//2], self.heap[ind] = self.heap[ind], self.heap[(ind-1)//2]\n            \n    def extract(self):\n        self.size -= 1\n        minval = self.heap[0].val\n        self.heap[self.size].ind = 0\n        self.heap[0] = self.heap[self.size]\n        ind = 0\n        while(2*ind + 1 < self.size):\n            swap_ind = 2 * ind + 1\n            if 2 * ind + 2 < self.size and self.heap[2 * ind + 2].val < self.heap[2 * ind + 1].val:\n                swap_ind += 1\n            if self.heap[swap_ind].val < self.heap[ind].val:\n                self.heap[swap_ind].ind, self.heap[ind].ind = ind, swap_ind\n                self.heap[swap_ind], self.heap[ind] = self.heap[ind], self.heap[swap_ind]\n                ind = swap_ind\n            else:\n                break\n        return minval\n                \nclass Solution:\n    def get_neighbors(self, pos):\n        neigh = []\n        if pos[0] < self.M - 1:\n            neigh.append([pos[0] + 1, pos[1]])\n        if pos[0] > 0:\n            neigh.append([pos[0] - 1, pos[1]])\n        if pos[1] < self.N -1:\n            neigh.append([pos[0], pos[1] + 1])\n        if pos[1] > 0:\n            neigh.append([pos[0], pos[1] - 1])\n        # print(neigh)\n        return neigh\n    \n    def argmin(self, dct):\n        minval = float('inf')\n        minkey = None\n        for k, v in dct.items():\n            if v < minval:\n                minval = v\n                minkey = k\n        return minkey, minval\n        \n    def shortestPath3(self, grid: List[List[int]], k: int) -> int:\n        self.M = len(grid)\n        self.N = len(grid[0])\n        dist = {(i, j , l) : float(\\\"inf\\\") for i in range(self.M) for j in range(self.N) for l in range(k+1)}\n        V = set()\n        for i in range(k+1):\n            dist[(0, 0, i)] = 0\n            \n        for i in range(self.M * self.N * (k+1)):\n            node, val = self.argmin(dist)\n            # if node == None:\n            #     print(dist)\n            # print(i, node, val)\n            if node == (self.M - 1, self.N -1, 0):\n                return val\n            if node == None:\n                return -1\n            V.add(node)\n            dist.pop(node)\n            neigh = self.get_neighbors(node[:2])\n            cost = [grid[n[0]][n[1]] for n in neigh]\n            neighk = [(n[0], n[1], l) for j, n in enumerate(neigh) for l in range(node[2] - cost[j] + 1)]\n            neighk = [n for n in neighk if n not in V]\n            for n in neighk:\n                # print(n , node)\n                dist[n] = min(dist[n], val + 1)\n        return dist[(self.M-1, self.N-1, 0)]\n    \n    def shortestPath2(self, grid: List[List[int]], k: int) -> int:\n        M = len(grid)\n        N = len(grid[0])\n        V = set()\n        queue = [(0, 0, k, 0)]\n        neighbors = [(0, 1), (1, 0), (-1, 0), (0, -1)]\n        while len(queue) > 0:\n            node = queue.pop(0)\n            V.add(node[:3])\n            if node[0] == M -1 and node[1] == N - 1:\n                return node[3]\n            for n in neighbors:\n                xnew = n[0] + node[0]\n                ynew = n[1] + node[1]\n                if 0 <= xnew < M and 0 <= ynew < N and (node[2] - grid[xnew][ynew]) >= 0:\n                    newnode = (xnew, ynew, node[2] - grid[xnew][ynew], node[3] + 1)\n                    if newnode in V:\n                        continue\n                    queue.append(newnode)\n        return -1\n            \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque()\n        visited = set()\n        queue.append((0, 0, k, 0))\n        while queue:\n            i, j, r, l = queue.popleft()\n            if (i, j, r) in visited:\n                continue\n            visited.add((i,j,r))\n            if grid[i][j] == 1:\n                r -= 1\n            if r < 0:\n                continue\n            if i == len(grid)-1 and j == len(grid[0])-1:\n                return l\n            neighbors = {(1,0), (0,1), (-1,0), (0,-1)}\n            for n in neighbors:\n                x,y=i+n[0],j+n[1]\n                if 0<=x<len(grid) and 0<=y<len(grid[0]):\n                    queue.append((x,y,r,l+1))\n        return -1\n                \n                ", "from typing import List\nfrom functools import lru_cache\nimport collections\nimport heapq\nimport itertools\nimport bisect\nimport copy\nimport random\nimport re\nimport fractions\nimport math\nimport functools\n\nmod = 10 ** 9 + 7\n\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not len(grid) or not len(grid[0]):\n            return 0\n        m, n = len(grid), len(grid[0])\n        \n        if k >= m + n - 3:\n            return m + n - 2\n\n        def neighbors(i, j):\n            for ni, nj in ((i + 1, j), (i, j + 1), (i - 1, j), (i, j - 1)):\n                if 0 <= ni < m and 0 <= nj < n:\n                    yield ni, nj\n\n        start = (0, 0, k)\n        seen = {start}\n        q = collections.deque([(0, start)])\n        while q:\n            step, (i, j, k) = q.popleft()\n            if (i, j) == (m - 1, n - 1):\n                return step\n            # if k >= m + n - 3 - i - j:\n            #     print(i, j, k)\n            #     return step + m + n - 2 - i - j\n            \n            for ni, nj in neighbors(i, j):\n                nk = k - grid[ni][nj]\n                state = (ni, nj, nk)\n                if nk >= 0 and state not in seen:\n                    q.append((step + 1, state))\n                    seen.add(state)\n\n        return -1\n\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q, nq, d = set([(0,0)]), set(), {(0,0):(0,0)}\n        while q:\n            for i,j in q:\n                dist, obst = d[(i,j)]\n                for m,n in [(i-1,j),(i,j-1),(i+1,j),(i,j+1)]:\n                    if 0<=m<len(grid) and 0<=n<len(grid[0]):\n                        if obst+grid[m][n] < d.get((m,n),(0,float('inf')))[1]:\n                            d[(m,n)] = (dist+1, obst+grid[m][n])\n                            nq.add((m,n))\n                dist, obst = d.get((len(grid)-1,len(grid[0])-1), (0,float('inf')))\n                if obst <= k:\n                    return dist\n            q, nq = nq, set()\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        visited = [[[False for _ in range(k+1)] for _ in range(n)] for _ in range(m)]\n        # visited=[[False for _ in range(n)] for _ in range(m)]\n        \n       # k - grid[0][0] - grid[m-1][n-1] \u662f\u56e0\u4e3a\u5982\u679c\u8d77\u70b9\u6216\u8005\u7ec8\u70b9\u662fobstacles, \u90a3\u4e48\u9700\u8981\u9884\u7559\u51fa\u6765\u4e00\u5b9a\u7684k\u6765\u7834\u574fobstacle        \n        initialK = k - grid[0][0] - grid[m-1][n-1];\n        \n        # visited[0][0] = (True, initialK)\n        \n        if initialK < 0: \n            return -1\n        visited[0][0][initialK] = True\n        \n        initial = ((0,0), initialK)\n        queue = [initial]\n        length = 0\n        \n        while queue:\n            size = len(queue)\n            length += 1\n            for _ in range(size):\n                node, kLeft = queue.pop(0)\n                x,y = node\n                # this is just for initial node is destination                \n                if kLeft >= 0 and x == m-1 and y == n-1:\n                    return length-1\n                \n                for direction in [(1,0),(-1,0),(0,1),(0,-1)]:\n                    nextX = x+direction[0]\n                    nextY = y+direction[1]\n        \n                    if 0<=nextX<m and 0<=nextY<n:\n                        nextKLeft = kLeft - grid[nextX][nextY]\n                        if nextKLeft < 0 or visited[nextX][nextY][nextKLeft]:\n                            #\u4e0d\u7b26\u5408\u6761\u4ef6, \u6216\u8005visited\u8fc7\u5e76\u4e14k\u8fd8\u662f\u540c\u4e00\u4e2a\u72b6\u6001\u7684\u53ef\u4ee5\u526a\u679d\n                            continue\n                        else:\n                            if nextX == m-1 and nextY == n-1:\n                                return length\n                            queue.append(((nextX, nextY), nextKLeft))\n                            visited[nextX][nextY][nextKLeft] = True\n                            \n        return -1\n                        \n                            \n", "\\\"\\\"\\\"\nupper left to bottom right\n\nperhaps we can use dp to find the minimum number of steps with x amount of obstacles remaining that we can remove\n3d dp array\nreturn min(dp[-1][-1]) at end\nm*n*k time complexity\ninitialize as float('-inf')\n\\\"\\\"\\\"\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque()\n        visited = set()\n        queue.append((0, 0, k, 0))\n        while queue:\n            i, j, r, l = queue.popleft()\n            if (i, j, r) in visited:\n                continue\n            visited.add((i,j,r))\n            if grid[i][j] == 1:\n                r -= 1\n            if r < 0:\n                continue\n            if i == len(grid)-1 and j == len(grid[0])-1:\n                return l\n            neighbors = {(1,0), (0,1), (-1,0), (0,-1)}\n            for n in neighbors:\n                x,y=i+n[0],j+n[1]\n                if 0<=x<len(grid) and 0<=y<len(grid[0]):\n                    queue.append((x,y,r,l+1))\n        return -1\n                \n            \n        ", "from collections import defaultdict, deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def getNei(x,y):\n            for dx,dy in dirs:\n                xn,yn = x+dx,y+dy\n                if 0<=xn<M and 0<=yn<N:\n                    yield xn,yn\n                \n        dirs = [(1,0),(0,1),(-1,0),(0,-1)]\n        M, N = len(grid), len(grid[0])\n        visited = [[[None]*(k+1) for _ in range(N)] for _ in range(M)]\n        \n        # visited[0][0][k] = True\n        \n        queue = deque([(0,0,k,0)])\n        \n        while queue:\n            i, j, kk, cost = queue.popleft()\n            \n            if i==M-1 and j==N-1:\n                return cost\n            \n            if visited[i][j][kk]:\n                continue\n            visited[i][j][kk] = True\n            \n            for x, y in getNei(i, j):\n                if grid[x][y] == 1:\n                    if kk > 0:\n                        queue.append((x, y, kk-1, cost+1))\n                else:\n                    queue.append((x, y, kk, cost+1))\n        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        cur_min = -1\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            if row == len(grid) - 1 and col == len(grid[0]) - 1:\n                if cur_min == -1:\n                    cur_min = dist\n                else:\n                    cur_min = min(cur_min, dist)\n            if cur_min != -1 and dist >= cur_min:\n                continue\n            for i, j in directions:\n                if row+i < len(grid) and row+i >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (row+i, col+j, cur_k) not in visited and grid[row+i][col+j] == 0:\n                        q.append((row+i, col+j, dist+1, cur_k))\n                        visited.add((row+i, col+j, cur_k))\n                    if (row+i, col+j, cur_k-1) not in visited and grid[row+i][col+j] == 1:\n                        if cur_k > 0:\n                            q.append((row+i, col+j, dist+1, cur_k-1))\n                            visited.add((row+i, col+j, cur_k-1))\n        return cur_min\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return -1\n\n        def boundary_check(r, c):\n            return 0 <= r < len(grid) and 0 <= c < len(grid[0])\n\n        q = deque([((0, 0, k), 0)])\n        visited = set((0, 0, k))\n        directions = ((0, 1), (0, -1), (1, 0), (-1, 0))\n        end_cell = (len(grid)-1, len(grid[0])-1)\n\n        while q:\n            (r, c, obst_rem), jumps = q.popleft()\n            if (r, c) == end_cell:\n                return jumps\n\n            for x, y in directions:\n                nxt_r, nxt_c = r + x, c + y\n                if boundary_check(nxt_r, nxt_c):\n                    if grid[nxt_r][nxt_c] == 0:\n                        nxt_state = (nxt_r, nxt_c, obst_rem)\n                    elif obst_rem > 0:\n                        nxt_state = (nxt_r, nxt_c, obst_rem-1)\n                    else:\n                        continue\n                    if (r, c) == end_cell:\n                        return jumps + 1\n                    if nxt_state not in visited:\n                        visited.add(nxt_state)\n                        q.append((nxt_state, jumps+1))\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque()\n        visited = set()\n        queue.append((0, 0, k, 0))\n        while queue:\n            i, j, r, l = queue.popleft()\n            if (i, j, r) in visited:\n                continue\n            visited.add((i,j,r))\n            if grid[i][j] == 1:\n                r -= 1\n            if r < 0:\n                continue\n            if i == len(grid)-1 and j == len(grid[0])-1:\n                return l\n            neighbors = {(1,0), (0,1), (-1,0), (0,-1)}\n            for n in neighbors:\n                x,y=i+n[0],j+n[1]\n                if 0<=x<len(grid) and 0<=y<len(grid[0]):\n                    queue.append((x,y,r,l+1))\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q=[]\n        n=len(grid)\n        m=len(grid[0])\n        v={}\n        q.append([0,0,0,k])\n        while(q):\n            i,j,d,r=q.pop(0)\n            if(i==n-1 and j==m-1):\n                return d\n            let=[[i+1,j],[i,j+1],[i-1,j],[i,j-1]]\n            for x,y in let:\n                if(0<=x<n and 0<=y<m):\n                    if(grid[x][y]==0 and (x,y,r) not in v):\n                        v[(x,y,r)]=1\n                        q.append([x,y,d+1,r])\n                    else:\n                        if(r>0 and (x,y,r) not in v):\n                            v[(x,y,r)]=1\n                            q.append([x,y,d+1,r-1])\n        return -1\n                        \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        nrows = len(grid)\n        ncols = len(grid[0])\n        if nrows == 1 and ncols ==1:\n            return 0\n        step = 1\n        \n        # if k > nrows-1 + ncols-1:\n        #     return nrows-1+ncols-1\n        \n        q = collections.deque()\n        visited = set([(0,0, k)])\n        q.append((0,0, k, step))\n        \n        def neigh(x,y):\n            tocheck = [(x+1,y), (x, y+1), (x-1, y), (x, y-1)]\n            nlist = []\n            for n in tocheck:\n                if 0<=n[0]<nrows and 0<= n[1]<ncols:\n                    nlist.append(n)\n            return nlist\n        \n        while(q):\n            i, j, k, step  = q.popleft()\n            neighs = neigh(i,j)\n            if i == nrows-1 and j == ncols-1:\n                return step\n            if neighs:\n                for n in neighs:\n                    if grid[n[0]][n[1]] == 1 and k>0 and (n[0], n[1], k-1) not in visited:\n                        q.append((n[0], n[1], k-1, step+1))\n                        visited.add((n[0], n[1], k-1))\n                        \n                    if grid[n[0]][n[1]] == 0 and (n[0], n[1], k) not in visited:\n                        if n[0] == nrows-1 and n[1] == ncols-1:\n                            return step\n                        q.append((n[0], n[1], k, step+1))\n                        visited.add((n[0], n[1], k))\n        \n        return -1\n    \n    \n    # 1091 is shortest path in binary matrix\n    # time complexity is O(m*n*k)\n            \n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n\n        queue = deque([(0,0,k,0)])\n        visited = set([(0,0,k)])\n\n        if k > (len(grid)-1 + len(grid[0])-1):\n            return len(grid)-1 + len(grid[0])-1\n\n        while queue:\n            row, col, eliminate, steps = queue.popleft()\n            for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n                if (new_row >= 0 and\n                    new_row < len(grid) and\n                    new_col >= 0 and\n                    new_col < len(grid[0])):\n                    if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n                        visited.add((new_row, new_col, eliminate-1))\n                        queue.append((new_row, new_col, eliminate-1, steps+1))\n                    if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n                        if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n                            return steps+1\n                        visited.add((new_row, new_col, eliminate))\n                        queue.append((new_row, new_col, eliminate, steps+1))\n\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        n,m = len(grid),len(grid[0])\n        vis = set()\n        vis.add((0,0,0)) # i,j,obstacleCount \n        \n        q =  [(0,0,0,0)]  # steps, i,j,obstacleCount\n        \n        def neighbors(i,j,oc):\n            for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                if 0<=x < n and 0<=y < m :\n                    newoc = oc + grid[x][y]\n                    if newoc <= k and (x,y,newoc) not in vis : \n                        yield x,y,newoc\n        \n        while q : \n            steps,i,j,obstacleCount = q.pop(0)\n            \n            if i == n-1 and j == m-1 : \n                return steps \n            else:\n                for x,y,oc in neighbors(i,j,obstacleCount):\n                    vis.add((x,y,oc))\n                    q.append((steps+1,x,y,oc))\n        \n        return - 1\n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if grid[0][0] == 1 and k == 0:\n            return -1\n        m, n = len(grid), len(grid[0])\n        a = k if grid[0][0] == 0 else k-1\n        q = collections.deque([(0, 0, 0, a, [(0,0)])])\n        visited = set()\n        visited.add((0,0))\n        while q:\n            i, j, step, available, path = q.popleft()\n            if i == m-1 and j == n-1:\n                return step\n            for ni, nj in [[i+1, j], [i-1, j], [i, j+1], [i, j-1]]:\n                if 0 <= ni < m and 0 <= nj < n:\n                    if grid[ni][nj] == 1 and not available:\n                        continue\n                    if (ni, nj, available) not in visited:\n                        visited.add((ni, nj, available))\n                        if grid[ni][nj] == 0:\n                            q.append([ni, nj, step+1, available, path+[(ni, nj)]])\n                        if grid[ni][nj] == 1:\n                            if available:\n                                q.append([ni, nj, step+1, available-1, path+[(ni, nj)]])                                    \n        return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rowlen = len(grid)\n        collen = len(grid[0])            \n        \n        visited = set()\n        visited.add((0,0,k))\n        \n        q = deque([(0,0,k, 0)])\n        \n        def get_nexts(x,y):\n            return [(nx,ny) for (nx,ny) in [(x+1,y), (x-1, y), (x, y+1), (x, y-1)] if 0<=nx<rowlen and 0<=ny<collen]\n        \n        while q:\n            x,y,k,path_count = q.popleft()       \n            \n            if (x,y) == (rowlen-1, collen-1): return path_count\n                        \n            nexts = get_nexts(x,y)\n            \n            for nx,ny in nexts:                \n                if grid[nx][ny] == 1 and not k: continue\n                if grid[nx][ny] == 1 and (nx,ny,k-1) in visited: continue\n                if grid[nx][ny] == 0 and (nx,ny,k) in visited: continue\n                    \n                if grid[nx][ny] == 1:\n                    visited.add((nx,ny,k-1))\n                    q.append((nx,ny,k-1,path_count+1))\n                else:\n                    if (nx,ny) == (rowlen-1, collen-1): return path_count+1\n                    visited.add((nx,ny,k))\n                    q.append((nx,ny,k,path_count+1))                \n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if grid[0][0] == 1 and k == 0:\n            return -1\n        m, n = len(grid), len(grid[0])\n        a = k if grid[0][0] == 0 else k-1\n        q = collections.deque([(0, 0, 0, a)])\n        visited = set()\n        visited.add((0,0))\n        while q:\n            i, j, step, available = q.popleft()\n            if i == m-1 and j == n-1:\n                return step\n            for ni, nj in [[i+1, j], [i-1, j], [i, j+1], [i, j-1]]:\n                if 0 <= ni < m and 0 <= nj < n:\n                    if grid[ni][nj] == 1 and not available:\n                        continue\n                    if (ni, nj, available) not in visited:\n                        visited.add((ni, nj, available))\n                        if grid[ni][nj] == 0:\n                            q.append([ni, nj, step+1, available])\n                        if grid[ni][nj] == 1:\n                            if available:\n                                q.append([ni, nj, step+1, available-1])                                    \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m ,n = len(grid), len(grid[0])\n        if m == n == 1:\n            return 0\n        queue = [(0, 0, k)]\n        visited = set((0,0))\n        steps = 0\n        \n        while queue:\n            new_queue = []\n            for x, y, obs in queue:\n                for i, j in ((x+1,y), (x-1, y), (x, y+1), (x, y-1)):\n                    if 0 <= i < m and  0 <= j < n:\n                        if grid[i][j] == 1 and obs > 0 and (i, j, obs - 1) not in visited:\n                            new_queue.append((i, j, obs - 1))\n                            visited.add((i,j, obs - 1))\n                        if grid[i][j] == 0 and (i,j,obs) not in visited:\n                            if i == m-1 and j == n-1:\n                                return steps + 1\n                            visited.add((i, j, obs))\n                            new_queue.append((i, j, obs))\n                            \n            if new_queue:\n                queue = new_queue\n                steps += 1\n            else:\n                break\n                \n        return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        cur_min = -1\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            if row == len(grid) - 1 and col == len(grid[0]) - 1:\n                if cur_min == -1:\n                    return dist\n            for i, j in directions:\n                if row+i < len(grid) and row+i >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (row+i, col+j, cur_k) not in visited and grid[row+i][col+j] == 0:\n                        q.append((row+i, col+j, dist+1, cur_k))\n                        visited.add((row+i, col+j, cur_k))\n                    if (row+i, col+j, cur_k-1) not in visited and grid[row+i][col+j] == 1:\n                        if cur_k > 0:\n                            q.append((row+i, col+j, dist+1, cur_k-1))\n                            visited.add((row+i, col+j, cur_k-1))\n        return cur_min\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rowlen = len(grid)\n        collen = len(grid[0])\n        visited = set()\n        visited.add((0,0,k))\n        \n        q = deque([(0,0,k, 0)])\n        \n        def get_nexts(x,y):\n            return [(nx,ny) for (nx,ny) in [(x+1,y), (x-1, y), (x, y+1), (x, y-1)] if 0<=nx<rowlen and 0<=ny<collen]\n        \n        while q:\n            x,y,k,path_count = q.popleft()       \n            \n            if (x,y) == (rowlen-1, collen-1): return path_count\n                        \n            nexts = get_nexts(x,y)\n            \n            for nx,ny in nexts:                \n                if grid[nx][ny] == 1 and not k: continue\n                if grid[nx][ny] == 1 and (nx,ny,k-1) in visited: continue\n                if grid[nx][ny] == 0 and (nx,ny,k) in visited: continue\n                    \n                if grid[nx][ny] == 1:\n                    visited.add((nx,ny,k-1))\n                    q.append((nx,ny,k-1,path_count+1))\n                else:\n                    if (nx,ny) == (rowlen-1, collen-1): return path_count+1\n                    visited.add((nx,ny,k))\n                    q.append((nx,ny,k,path_count+1))                \n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if grid[0][0] == 1 and k == 0:\n            return -1\n        m, n = len(grid), len(grid[0])\n        a = k if grid[0][0] == 0 else k-1\n        q = collections.deque([(0, 0, 0, a, [(0,0)])])\n        visited = set()\n        visited.add((0,0))\n        while q:\n            i, j, step, available, path = q.popleft()\n            if i == m-1 and j == n-1:\n                #print(path)\n                return step\n            for ni, nj in [[i+1, j], [i-1, j], [i, j+1], [i, j-1]]:\n                if 0 <= ni < m and 0 <= nj < n:\n                    if grid[ni][nj] == 1 and not available:\n                        continue\n                    if (ni, nj, available) not in visited:\n                        visited.add((ni, nj, available))\n                        if grid[ni][nj] == 0:\n                            q.append([ni, nj, step+1, available, path+[(ni, nj)]])\n                        if grid[ni][nj] == 1:\n                            if available:\n                                q.append([ni, nj, step+1, available-1, path+[(ni, nj)]])                  \n                        \n        return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        cur_min = -1\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            if row == len(grid) - 1 and col == len(grid[0]) - 1:\n                return dist\n            for i, j in directions:\n                if row+i < len(grid) and row+i >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (row+i, col+j, cur_k) not in visited and grid[row+i][col+j] == 0:\n                        q.append((row+i, col+j, dist+1, cur_k))\n                        visited.add((row+i, col+j, cur_k))\n                    if (row+i, col+j, cur_k-1) not in visited and grid[row+i][col+j] == 1:\n                        if cur_k > 0:\n                            q.append((row+i, col+j, dist+1, cur_k-1))\n                            visited.add((row+i, col+j, cur_k-1))\n        return cur_min\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        cur_min = -1\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            if row == len(grid) - 1 and col == len(grid[0]) - 1:\n                return dist\n            for i, j in directions:\n                if row+i < len(grid) and row+i >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (row+i, col+j, cur_k) not in visited and grid[row+i][col+j] == 0:\n                        q.append((row+i, col+j, dist+1, cur_k))\n                        visited.add((row+i, col+j, cur_k))\n                    if (row+i, col+j, cur_k-1) not in visited and grid[row+i][col+j] == 1:\n                        if cur_k > 0:\n                            q.append((row+i, col+j, dist+1, cur_k-1))\n                            visited.add((row+i, col+j, cur_k-1))\n        return -1\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = set()\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and (ii, jj, k) not in seen:\n                            seen.add((ii, jj, k))\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and (ii, jj, k-1) not in seen:\n                            seen.add((ii, jj, k-1))\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = {}\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and ((ii, jj) not in seen or k > seen[(ii, jj)]):\n                            seen[(ii, jj)] = k\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and ((ii, jj) not in seen or k-1 > seen[(ii, jj)]):\n                            seen[(ii, jj)] = k-1\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1\n    \n    # bidirection bfs\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q1, q2 = {}, {}\n        q1[(0, 0)] = 0\n        q2[(m-1, n-1)] = 0\n        level = 0\n        seen1, seen2 = {}, {}\n        seen1[(0, 0)] = 0\n        seen2[(m-1, n-1)] = 0\n        \n        while q1 and q2:\n            tmp = {}\n            if len(q2) < len(q1):\n                q1, q2 = q2, q1\n                seen1, seen2 = seen2, seen1\n            for (i, j), k in q1.items():\n                if (i, j) in q2 and k+q2[(i, j)] <= K:\n                    return level\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and ((ii, jj) not in seen1 or k < seen1[(ii, jj)]):\n                            seen1[(ii, jj)] = k\n                            tmp[(ii, jj)] = k\n                        if grid[ii][jj] == 1 and k < K and ((ii, jj) not in seen1 or k+1 < seen1[(ii, jj)]):\n                            seen1[(ii, jj)] = k+1\n                            tmp[(ii, jj)] = k+1\n            q1 = tmp\n            level += 1\n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        if len(grid[0]) == 1 and len(grid) == 1:\n            return 0\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            for i, j in directions:\n                if row+i < len(grid) and row+i >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (row+i, col+j, cur_k) not in visited and grid[row+i][col+j] == 0:\n                        if row+i == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                            return dist + 1\n                        q.append((row+i, col+j, dist+1, cur_k))\n                        visited.add((row+i, col+j, cur_k))\n                    if (row+i, col+j, cur_k-1) not in visited and grid[row+i][col+j] == 1:\n                        if cur_k > 0:\n                            if row+i == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                                return dist + 1\n                            q.append((row+i, col+j, dist+1, cur_k-1))\n                            visited.add((row+i, col+j, cur_k-1))\n        return -1\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        q = deque([(0,0,0,k)])\n        visited = set([(0,0,k)])\n        while q:\n            row, col, dist, cur_k = q.popleft()\n            if row == len(grid) - 1 and col == len(grid[0]) - 1:\n                return dist\n            for i, j in directions:\n                if row+i < len(grid) and row+i >= 0 and col+j < len(grid[0]) and col+j >= 0: \n                    if (row+i, col+j, cur_k) not in visited and grid[row+i][col+j] == 0:\n                        if row+i == len(grid) - 1 and col+j == len(grid[0]) - 1:\n                            return dist + 1\n                        q.append((row+i, col+j, dist+1, cur_k))\n                        visited.add((row+i, col+j, cur_k))\n                    if (row+i, col+j, cur_k-1) not in visited and grid[row+i][col+j] == 1:\n                        if cur_k > 0:\n                            q.append((row+i, col+j, dist+1, cur_k-1))\n                            visited.add((row+i, col+j, cur_k-1))\n        return -1\n\n# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "from collections import deque\nfrom typing import List\n\nclass Solution:\n    def getNeighbors(self, width, height, node):\n        row, column = node\n        \n        for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:\n            rr, cc = row + dr, column + dc\n            \n            if 0 <= rr < height and 0 <= cc < width:\n                yield (rr, cc)\n\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        height, width = len(grid), len(grid[0])\n        \n        queue = deque()\n        queue.append(((0, 0), k))\n        \n        result, visited = 0, set()\n        visited.add(((0, 0), k))\n\n        while queue:\n            length = len(queue)\n            \n            for _ in range(length):\n                (node, remove_capacity) = queue.popleft()\n            \n                if node == (height-1, width-1):\n                    return result\n    \n                for neighbor in self.getNeighbors(width, height, node):\n                    key = (neighbor, remove_capacity - grid[neighbor[0]][neighbor[1]])\n\n                    if key not in visited and key[1] >= 0:\n                        queue.append(key)\n                        visited.add(key)\n            \n            result += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # traverse upper left to lower right\n        # double for loop \n        # visited = [[0 for x in row] for row in grid] \n        #don't use visited grid, use viisted set that keeps track of remaining obstacles instead.\n    \n        # obstacles = []\n        # for i in range(len(grid)):\n        #     for j in range(len(grid[0])):\n        #         if grid[i][j] == 0: #and visited[i][j] != 1:\n        #             # self.traverse(i,j, grid, visited, k)\n        #             continue\n        #         else:\n        #             obstacles.append((i,j))\n            \n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        directions = [[-1,0], [1,0], [0,-1], [0,1]]\n        queue = deque()\n        queue.append((0,0,k,0))\n        # need to keep track of number of steps. put it in the tuple alongside the coordinates\n        visited = set((0,0,k))\n        count = 0\n        while queue:\n            x, y, obstacles, steps = queue.popleft()\n            visited.add((x, y, obstacles))\n            \n            for dx,dy in directions:\n                if 0<=x+dx<len(grid) and 0<=y+dy<len(grid[0]):\n                    if grid[x+dx][y+dy] == 0 and (x+dx, y+dy, obstacles) not in visited:\n                        if x+dx == len(grid)-1 and y+dy == len(grid[0]) -1:\n                            return steps+1\n                        queue.append((x+dx, y+dy, obstacles, steps+1))\n                        visited.add((x+dx, y+dy, obstacles))\n                        \n                    if grid[x+dx][y+dy] == 1 and obstacles>0 and (x+dx, y+dy, obstacles-1) not in visited:\n                        queue.append((x+dx, y+dy, obstacles-1, steps+1))\n                        visited.add((x+dx, y+dy, obstacles-1))\n                        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        r, c = len(grid), len(grid[0])\n        if r == 1 and c == 1:\n            return 0\n        q = deque([(0, 0, 0, 0)])    # row, col, num of obstables met, steps \n        visited = set((0, 0, 0))\n        \n        while q:\n            row, col, met, step = q.popleft()\n            if met > k:\n                continue\n            if row == r-1 and col == c-1:\n                return step\n            for nr, nc in [[row+1, col], [row-1, col], [row, col+1], [row, col-1]]:\n                if 0 <= nr < r and 0 <= nc < c:\n                    if grid[nr][nc] == 1 and met+1 <= k and (nr, nc, met+1) not in visited:\n                        visited.add((nr, nc, met+1))\n                        q.append((nr, nc, met+1, step+1))\n                    if grid[nr][nc] == 0 and met <= k and (nr, nc, met) not in visited:\n                        visited.add((nr, nc, met))\n                        q.append((nr, nc, met, step+1))\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        visited = set()\n        q = collections.deque([[0, 0, 0, k]])\n        m = len(grid)\n        n = len(grid[0])\n        while q:\n            i, j, d, score = q.popleft()\n            if i == m - 1 and j == n - 1:\n                return d\n            if (i, j, score) in visited:\n                continue\n            visited.add((i, j, score))\n            for x, y in [[1, 0], [0, 1], [-1, 0], [0, -1]]:\n                r, c = x + i, y + j\n                if r < 0 or r >= m or c < 0 or c >= n or score < grid[r][c] \\\\\n                    or (r, c, score - grid[r][c]) in visited:\n                    continue\n                q.append([r, c, d + 1, score - grid[r][c]])\n            \n        return -1\n            \n            ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        r, c = len(grid), len(grid[0])\n        if r == 1 and c == 1:\n            return 0\n        q = deque([(0, 0, 0, 0)])    # row, col, num of obstables met, steps \n        visited = set((0, 0, 0))\n        \n        while q:\n            row, col, met, step = q.popleft()\n            if row == r-1 and col == c-1:\n                return step\n            if met > k:\n                continue\n            for nr, nc in [[row+1, col], [row-1, col], [row, col+1], [row, col-1]]:\n                if 0 <= nr < r and 0 <= nc < c:\n                    if grid[nr][nc] == 1 and met+1 <= k and (nr, nc, met+1) not in visited:\n                        visited.add((nr, nc, met+1))\n                        q.append((nr, nc, met+1, step+1))\n                    if grid[nr][nc] == 0 and met   <= k and (nr, nc, met  ) not in visited:\n                        visited.add((nr, nc, met))\n                        q.append((nr, nc, met, step+1))\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # we perform BFS but we keep track of the number of obstacles we have removed to reach the current node along with the steps\n        # each node can be reached after removing different number of obstacles and so our state in BFS will not just be x,y but also the no of blocks we removed to reach the node\n        if len(grid) == 0 or len(grid[0]) == 0:\n            return -1\n        if grid[0][0] == 1:\n            queue = [(0,0,1,0)]\n            visited = set([(0,0,1)])\n        else:\n            queue = [(0,0,0,0)]\n            visited = set([(0,0,0)])\n        direction = [(-1,0),(1,0),(0,-1),(0,1)]\n        while queue != []:\n            current = queue.pop(0)\n            if current[0] == len(grid)-1 and current[1] == len(grid[0])-1:\n                return current[3]\n            for d in direction:\n                n = (current[0] + d[0],current[1] + d[1])\n                if 0<=n[0]<len(grid) and 0<=n[1]<len(grid[0]):\n                    blocks = current[2]\n                    if grid[n[0]][n[1]] == 1:\n                        blocks += 1 \n                    if blocks <= k and (n[0],n[1],blocks) not in visited:\n                        queue.append((n[0],n[1],blocks,current[3]+1))\n                        visited.add((n[0],n[1],blocks))       \n        return -1\n", "class Solution:\n    def shortestPath(self, grid, k):\n        m = len(grid)\n        n = len(grid[0])\n        q = [(0,0,0,0)]\n        dirs = [(1,0),(-1,0),(0,1),(0,-1)]\n        visited = set((0,0,0))\n        i = j = obs = 0\n        \n        while q:\n            x,y,obs,steps = q.pop(0)\n            if x == m-1 and y == n-1:\n                return steps\n            for dx,dy in dirs:\n                i = x + dx\n                j = y + dy\n                if 0<=i<m and 0<=j<n: \n                    newObs = obs + grid[i][j]\n                    if newObs <= k and (i,j,newObs) not in visited:\n                        q.append((i,j,newObs,steps+1))\n                        visited.add((i,j,newObs))\n                    \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q, d = deque([(0,0)]), {(0,0):(0,0)}\n        while q:\n            i,j = q.popleft()\n            dist, obst = d[(i,j)]\n            for m,n in [(i-1,j),(i,j-1),(i+1,j),(i,j+1)]:\n                if 0<=m<len(grid) and 0<=n<len(grid[0]) and obst+grid[m][n] < d.get((m,n),(0,float('inf')))[1]:\n                        d[(m,n)] = (dist+1, obst+grid[m][n])\n                        q.append((m,n))\n            dist, obst = d.get((len(grid)-1,len(grid[0])-1), (0,float('inf')))\n            if obst <= k: return dist\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        \n        def move(pos_x, pos_y, obs, steps):\n            if pos_x < 0 or pos_x>=len(grid) or pos_y<0 or pos_y>=len(grid[0]):\n                return\n            \n            if grid[pos_x][pos_y] == 1:\n                if obs == 0:\n                    return\n                obs -= 1\n            \n            if self.memo.get((pos_x, pos_y, obs), 2000) <= steps:\n                return\n            self.memo.update({(pos_x, pos_y, obs): steps})\n            q.append((pos_x, pos_y, obs, steps))\n            if (pos_x==len(grid)-1) and (pos_y==len(grid[0])-1):\n                self.ans = steps\n            \n        \n        self.ans = None\n        q = deque([(0, 0, k, 0)])\n        self.memo = {(0,0,k):0}\n        \n        while q:\n            pos_x, pos_y, obs, steps = q.popleft()\n            if (pos_x==len(grid)-1) and (pos_y==len(grid[0])-1):\n                return steps\n            move(pos_x-1, pos_y, obs, steps+1)\n            move(pos_x+1, pos_y, obs, steps+1)\n            move(pos_x, pos_y-1, obs, steps+1)\n            move(pos_x, pos_y+1, obs, steps+1)\n            if self.ans is not None:\n                return self.ans\n\n        return -1\n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        if not grid or not grid[0]:\n            return 0\n        n = len(grid)\n        m = len(grid[0])\n        hp = []\n        heapq.heappush(hp, (0, 0, 0, 0))\n        visited = set()\n        visited.add((0, 0, 0))\n        while hp:\n            step, d, i, j = heapq.heappop(hp)\n            if i == n - 1 and j == m - 1:\n                return step\n            for x, y in [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]:\n                if x < 0 or x >= n or y < 0 or y >= m or (x, y, d + grid[x][y]) in visited or grid[x][y] + d > k:\n                    continue\n                visited.add((x, y, grid[x][y] + d))\n                heapq.heappush(hp, (step + 1, d + grid[x][y], x, y))\n        return -1\n", "import heapq\n\nclass Solution:\n  def shortestPath(self, grid: List[List[int]], k: int) -> int:\n    m, n = len(grid), len(grid[0])\n    # a-star search\n    # state: (heuristic + moves, moves, row, col, num obstacle removed)\n    q, seen = [(m - 1 + n - 1 + 0, 0, 0, 0, 0)], set()\n    while q:\n      _, d, x, y, z = heapq.heappop(q)\n      if (x, y) == (m - 1, n - 1):\n        return d\n      if (x, y, z) not in seen:\n        seen.add((x, y, z))\n        for dx, dy in [(-1, 0), (0, 1), (1, 0), (0, -1)]:\n          i, j = x + dx, y + dy\n          if 0 <= i < m and 0 <= j < n:\n            if grid[i][j] == 0:\n              heapq.heappush(q, (m - 1 - i + n - 1 - j + d + 1, d + 1, i, j, z))\n            elif z + 1 <= k:\n              # grid[i][j] == 1\n              heapq.heappush(q, (m - 1 - i + n - 1 - j + d + 1, d + 1, i, j, z + 1))\n    return -1", "from collections import deque\nimport numpy as np\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m=len(grid)\n        n=len(grid[0])\n        dq=deque()\n        cache={}\n        minStep=np.inf\n        s=(0,0,0,0)\n        cache[s[:3]]=s[-1]\n        dq.append(s)\n        while dq:\n            i,j,ob,step=dq.popleft()\n            if i==m-1 and j==n-1:\n                minStep=min(minStep,step)\n                continue\n            for x,y in [(i,j-1),(i,j+1),(i-1,j),(i+1,j)]:\n                if x>=0 and x<m and y>=0 and y<n:\n                    if ob+grid[x][y]>k or step+1>minStep:\n                        continue\n                    if (x,y,ob+grid[x][y]) not in cache or step+1<cache[(x,y,ob+grid[x][y])]:\n                        dq.append((x,y,ob+grid[x][y],step+1))\n                        cache[(x,y,ob+grid[x][y])]=step+1\n        return -1 if minStep==np.inf else minStep\n\n# This is a difficult problem, and illustrate well bfs, definitely need to review\n# 1. Basic idea is to BFS the whole grid, state is actually i,j and number of obstacles removed, this state is the key and value is the steps taken so far\n", "class Solution:\n    \n    dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]]\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return -1\n        \n        n, m = len(grid), len(grid[0])\n        \n        queue = deque()\n        queue.append((0, 0, k))\n        visited = set()\n        visited.add((0, 0, k))\n        \n        step = 0\n        while queue:\n            size = len(queue)\n            for _ in range(size):\n                i, j, chances = queue.popleft()\n                if i == n - 1 and j == m - 1:\n                    return step\n                \n                for d in Solution.dirs:\n                    x, y = i + d[0], j + d[1]\n                    if x < 0 or x >= n or y < 0 or y >= m:\n                        continue\n                    \n                    if grid[x][y] == 0:\n                        if (x, y, chances) not in visited:\n                            queue.append((x, y, chances))\n                            visited.add((x, y, chances))\n                    elif grid[x][y] == 1:\n                        if chances == 0:\n                            continue\n                        if (x, y, chances - 1) not in visited:\n                            queue.append((x, y, chances - 1))\n                            visited.add((x, y, chances - 1))\n            step += 1\n        \n        return -1", "from typing import *\nfrom collections import deque\n\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        # print(m, n, k)\n        dis = [[[float('inf') for _ in range(k + 1)] for _ in range(n)] for _ in range(m)]\n        dis[0][0][0] = 0\n\n        vis = [[[False for _ in range(k + 1)] for _ in range(n)] for _ in range(m)]\n        q = deque([(0, 0, k, 0)])\n        vis[0][0][k] = True\n\n        while q:\n            x, y, remain_chance, d = q.popleft()\n            # print(x, y, remain_chance, d)\n            if x == m - 1 and y == n - 1:  # reach destination\n                return d\n            dis[x][y][k] = d\n            for x1, y1 in [(x, y - 1), (x, y + 1), (x + 1, y), (x - 1, y)]:\n                if x1 < 0 or x1 >= m or y1 < 0 or y1 >= n:  # out of bounds\n                    continue\n                if grid[x1][y1] == 1:  # is obstacle\n                    if remain_chance == 0:\n                        continue\n                    if vis[x1][y1][remain_chance - 1]:\n                        continue\n                    q.append((x1, y1, remain_chance - 1, d + 1))\n                    vis[x1][y1][remain_chance - 1] = True\n                else:  # not obstacle\n                    if vis[x1][y1][remain_chance]:\n                        continue\n                    q.append((x1, y1, remain_chance, d + 1))\n                    vis[x1][y1][remain_chance] = True\n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m,n = len(grid), len(grid[0])\n        \n        # BFS\n        queue = deque([(0,0,0)])\n        seen = set([(0,0,0)])\n        nsteps = -1\n        while queue:\n            levelSize = len(queue)\n            nsteps += 1\n            for _ in range(levelSize):\n                i,j,t = queue.popleft()\n                if i==m-1 and j==n-1:\n                    return nsteps\n                for x,y in [(i+1,j), (i-1,j), (i,j+1), (i,j-1)]:\n                    if 0<=x<m and 0<=y<n:\n                        is_obs = grid[x][y]==1\n                        q = t+int(is_obs) # obstacles need to be killed\n                        if q<=k and (x,y,q) not in seen:\n                            queue.append( (x,y,q) )\n                            seen.add( (x,y,q) )\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: return -1\n        m, n = len(grid), len(grid[0])\n        if grid[0][0] != 0: return -1\n        if m == 1 and n == 1: return 0 # no need to walk\n        di = [(-1, 0), (1, 0), (0, -1), (0, 1)]\n        def get_nei(i, j): \n            return [(i+x, j+y) for (x, y) in di if 0<=i+x<=m-1 and 0<=j+y<=n-1]\n        \n        # seen = {(0, 0): 0}\n        seen = set([(0, 0, k)])\n        # seen2 = {(0, 0): k}\n        q = collections.deque()\n        q.append((0, 0, k, 0))\n        while q: \n            i, j, ob, depth = q.popleft()\n            for x, y in get_nei(i, j): \n                cob = ob\n                if x == m-1 and y == n-1 and cob >= 0: \n                    return depth+1\n                if grid[x][y] == 1 and cob > 0 and (x, y, cob-1) not in seen: \n                    seen.add((x, y, cob-1))\n                    q.append((x, y, cob-1, depth+1))\n                if grid[x][y] == 0 and cob >= 0 and (x, y, cob) not in seen: \n                    seen.add((x, y, cob))\n                    q.append((x, y, cob, depth+1))\n                    \n                \n                    # cob -= 1\n                    # if cob < 0: \n                    #     continue\n                # if (x, y, cob) in seen: \n                #     continue\n                # seen.add((x, y, cob))\n                # q.append((x, y, cob, depth+1))\n        return -1\n\n    \n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        EMPTY, OBSTACLE = 0, 1\n        m, n = len(grid), len(grid[0])\n        distance = defaultdict(lambda: math.inf)\n        distance[0, 0, 0] = 0\n        pq = [(0, 0, 0, 0)]\n        while pq:\n            d, e, i, j = heapq.heappop(pq)\n            if distance[e, i, j] < d:\n                continue\n            if i == m - 1 and j == n - 1:\n                return d\n            for ni, nj in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):\n                if 0 <= ni < m and 0 <= nj < n:\n                    ne = e + int(grid[ni][nj] == OBSTACLE)\n                    if ne <= k:\n                        nd = d + 1\n                        if nd < distance[ne, ni, nj]:\n                            distance[ne, ni, nj] = nd\n                            heapq.heappush(pq, (nd, ne, ni, nj))\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n\n        queue = deque([(0,0,k,0)])\n        visited = set([(0,0,k)])\n\n        if k > (len(grid)-1 + len(grid[0])-1):\n            return len(grid)-1 + len(grid[0])-1\n\n        while queue:\n            row, col, eliminate, steps = queue.popleft()\n            #print(steps,eliminate)\n            for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n                if (new_row >= 0 and\n                    new_row < len(grid) and\n                    new_col >= 0 and\n                    new_col < len(grid[0])):\n                    if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n                        visited.add((new_row, new_col, eliminate-1))\n                        queue.append((new_row, new_col, eliminate-1, steps+1))\n                        #print(queue)\n                    if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n                        if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n                            return steps+1\n                        visited.add((new_row, new_col, eliminate))\n                        queue.append((new_row, new_col, eliminate, steps+1))\n                        #print(queue)\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # This is basically BFS on state graph\n        # State is (path ending at P, k)\n        # We don't need the whole path because the first path ending at P willl\n        # be better than later paths ending at P with same k\n        # Hence, different paths ending with same P can be collapsed to one state\n        # represented by P\n        rows, cols = len(grid), len(grid[0])\n        if rows == 1 and cols == 1:\n            return 0\n\n        visited = set((0, 0, k))\n        q = deque([(0, 0, k, 0)])\n        while q:\n            r, c, k_rem, d = q.popleft()\n            edges = [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]\n            edges = [(x, y) for x, y in edges if x >= 0 and x < rows and y >= 0 and y < cols]\n            edges = [(x, y, (k_rem - 1) if grid[x][y] == 1 else k_rem) for x, y in edges]\n            edges = [edge for edge in edges if edge[2] >= 0 and edge not in visited]\n            for x, y, rem in edges:\n                if x == rows - 1 and y == cols - 1:\n                    return d + 1\n                q.append((x, y, rem, d + 1))\n                visited.add((x, y, rem))\n        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid:\n            return 0\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        m, n = len(grid), len(grid[0])\n        queue = deque([(0,0,0,k)])\n        visited = set()\n        visited.add((0,0,k))\n        direction = [[1,0],[0,1],[0,-1],[-1,0]]\n        \n        while queue:\n            cur_x, cur_y, cur_count, cur_k = queue.popleft()\n            for i, j in direction:\n                next_x = cur_x + i\n                next_y = cur_y + j\n                if 0 <= next_x < m and 0 <= next_y < n:\n                    if grid[next_x][next_y] == 1 and cur_k > 0 and (next_x, next_y, cur_k-1) not in visited:\n                        visited.add((next_x, next_y, cur_k-1))\n                        queue.append((next_x, next_y, cur_count+1, cur_k-1))\n                    \n                    if grid[next_x][next_y] == 0 and (next_x, next_y, cur_k) not in visited:\n                        if next_x == m-1 and next_y == n-1:\n                            return cur_count+1\n                        visited.add((next_x, next_y, cur_k))\n                        queue.append((next_x, next_y, cur_count+1, cur_k))\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        row, col = len(grid), len(grid[0])\n        q = collections.deque()\n        q.append((0, 0, 0, k))\n        visit = set()\n        while q:\n            x, y, dist, k = q.popleft()\n            if x == row - 1 and y == col - 1:\n                return dist\n            if (x, y, k) in visit:\n                continue\n            visit.add((x, y, k))\n            dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]]\n            for i, j in dirs:\n                if 0 <= x + i < row and 0 <= y + j < col:\n                    if grid[x + i][y + j] == 0:\n                        q.append((x + i, y + j, dist + 1, k))\n                    elif grid[x + i][y + j] == 1 and k > 0:\n                        q.append((x + i, y + j, dist + 1, k - 1))\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        cache = {} # The key should be (axis, key)\n        m = len(grid)\n        n = len(grid[0])\n        if m == 1 and n == 1:\n            if grid[0][0] == 0:\n                return 0\n            if grid[0][0] == 1:\n                if k >= 1:\n                    return 0\n                return -1\n            \n        def get_nexts(i, j, k):\n            nxts = [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]\n            nxts = [(x, y) for x, y in nxts \n                    if x >= 0 and x < m and y >= 0 and y < n \n                    and (x, y) not in pathnodes]\n            \n            nxts_steps = []\n            for x, y in nxts:\n                if grid[x][y] == 0:\n                    nxts_steps.append((x, y, k))\n                if grid[x][y] and k >= 1:\n                    nxts_steps.append((x, y, k - 1))\n            return nxts_steps\n        \n        pathnodes = set()\n        #bfs\n        roots = [(0, 0, k)]\n        d = 0\n        includes = set(roots)\n        while roots:\n            next_level = []\n            for root in roots:\n                nxts = get_nexts(*root)\n                for nxt in nxts:\n                    if nxt in includes:\n                        continue\n                    if nxt[:2] == (m - 1, n - 1):\n                        return d + 1\n                    next_level.append(nxt)\n                    includes.add(nxt)\n            roots = next_level\n            d += 1\n        \n        return -1\n        \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n, m = len(grid), len(grid[0])\n        if n==1 and m==1: return 0\n\n        dist = {(0, 0, k): 0}\n        queue = deque([(0, 0, k)])\n\n        while queue:\n            i, j, p = queue.popleft()\n            for r, s in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:\n                if r == n-1 and s == m-1:\n                    return dist[(i, j, p)]+1\n                if 0 <= r < n and 0 <= s < m:\n                    if grid[r][s] == 0 and (r, s, p) not in dist:\n                        dist[(r, s, p)] = dist[(i, j, p)]+1\n                        queue.append((r, s, p))\n                    elif p > 0 and (r, s, p-1) not in dist:\n                        dist[(r, s, p-1)] = dist[(i, j, p)]+1\n                        queue.append((r, s, p-1))\n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n        \n        q = collections.deque([(0, 0, 0, 0)])\n        m, n = len(grid), len(grid[0])\n        visited = set()\n         \n        while q:\n            x, y, obstacle, path = q.popleft()\n            for i, j in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):\n                if 0 <= i < m and 0 <= j < n:\n                    if grid[i][j] == 1 and obstacle < k and (i, j, obstacle + 1) not in visited:\n                        visited.add((i, j, obstacle + 1))\n                        q.append((i, j, obstacle + 1, path + 1))\n                    if grid[i][j] == 0 and (i, j, obstacle) not in visited:    \n                        if (i, j) == (m - 1, n - 1):\n                            return path + 1\n                        visited.add((i, j, obstacle))\n                        q.append((i, j, obstacle, path + 1))\n                        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        r, c = len(grid), len(grid[0])\n        if r == 1 and c == 1:\n            return 0\n        q = deque([(0, 0, 0, 0)])    # row, col, num of obstables met, steps \n        visited = set((0, 0, 0))\n        \n        while q:\n            row, col, met, step = q.popleft()\n            if row == r-1 and col == c-1:\n                return step\n            if met > k:\n                continue\n            for nr, nc in [[row+1, col], [row-1, col], [row, col+1], [row, col-1]]:\n                if 0 <= nr < r and 0 <= nc < c:\n                    if grid[nr][nc] == 1 and (nr, nc, met+1) not in visited:\n                        visited.add((nr, nc, met+1))\n                        q.append((nr, nc, met+1, step+1))\n                    if grid[nr][nc] == 0 and (nr, nc, met) not in visited:\n                        if nr == r-1 and nc == c-1:\n                            return step + 1\n                        visited.add((nr, nc, met))\n                        q.append((nr, nc, met, step+1))\n                        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, g: List[List[int]], k: int) -> int:\n        m, n = len(g), len(g[0])\n        q = collections.deque([(0, 0, k, 0)])\n        seen = {(0, 0, k)}\n        while q:\n            x, y, r, s = q.popleft()\n            if x==m-1 and y==n-1:\n                return s\n            for i, j in ((0, 1), (1, 0), (-1, 0), (0, -1)):\n                if 0<=x+i<m and 0<=y+j<n:\n                    nr = r-(g[x+i][y+j]==1)\n                    if (x+i, y+j, nr) not in seen and nr>=0:\n                        q.append((x+i, y+j, nr, s+1))\n                        seen.add((x+i, y+j, nr))\n        return -1\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         m, n = len(grid), len(grid[0])\n#         move = [(0,1), (1,0), (0,-1), (-1,0)]\n#         visited = set([])\n#         q = deque([(0,0,0,k)])\n#         while q:\n#             r, c, cur, cur_k = q.popleft()\n#             visited.add((r,c,cur_k))\n#             if r == m-1 and c == n-1:\n#                 return cur\n#             for dx, dy in move:\n#                 row, col = r+dy, c+dx\n#                 if 0<= row < m and 0 <= col < n:\n                \n#                     if grid[row][col] == 1 and cur_k > 0 and \\\\\n#                     (row, col, cur_k-1) not in visited:\n#                         q.append((row, col, cur+1, cur_k-1))\n#                         visited.add((row, col, cur_k-1))\n#                     if grid[row][col] == 0 and (row, col, cur_k) not in visited:\n#                         if row == m-1 and col == n-1:\n#                             return cur + 1\n#                         q.append((row, col, cur+1, cur_k))\n#                         visited.add((row, col, cur_k))\n                        \n        \n#         return -1\n", "class Solution:\n    def shortestPath(self, map: List[List[int]], k: int) -> int:\n        import collections\n        h, w = len(map), len(map[0])\n\n        def check_map(i, j, rw):\n            if i >= h or i < 0: return 1\n            if j >= w or j < 0: return 1\n            if map[i][j] == 1 and rw > 0: return -1\n            if map[i][j] == 1 and rw == 0: return 1\n\n            return 0\n\n                   # i    j    st rw\n        start_pos = (0, 0, 0, k)\n        q = collections.deque([])\n        q.append(start_pos)\n        seen = set()\n        seen.add((0, 0, k))\n        # vis[h-1][w-1]= \\\"X\\\"\n        while q:\n            # print(\\\"Q\\\",q)\n\n            i, j, step, rw = q.popleft()\n            if i == h - 1 and j == w - 1:\n                return step\n\n            fw = [i - 1, j]\n            bw = [i + 1, j]\n            lf = [i, j - 1]\n            rt = [i, j + 1]\n\n            moves = [bw, rt, lf, fw]\n\n    #         print(moves)\n            for move in moves:\n                ni, nj = move\n                # print(\\\">\\\",move)\n                map_state = check_map(ni, nj, rw)\n                if map_state in (0, -1) and (ni, nj, rw + map_state) not in seen:\n                    # if map_state == -1:\n                    # print(map_state)\n                    q.append([ni, nj, step + 1, rw + map_state])\n                    seen.add((ni, nj, rw + map_state))\n        return -1", "class Solution(object):\n\n    def shortestPath(self, grid, k):\n        \\\"\\\"\\\"\n        :type grid: List[List[int]]\n        :type k: int\n        :rtype: int\n        \\\"\\\"\\\"\n        def getNei(x,y):\n            if x+1 < m:\n                yield x+1,y,grid[x+1][y]\n            if y+1 < n:\n                yield x,y+1,grid[x][y+1]\n            if x>0:\n                yield x-1,y,grid[x-1][y]\n            if y>0:\n                yield x,y-1,grid[x][y-1]\n                \n        m,n = len(grid),len(grid[0])\n        cost = [[float('inf')]*n for _ in range(m)]\n        cost[0][0] = 0\n        #x,y,steps,cost left\n        q = collections.deque([(0,0,0,k)])\n        while q:\n            x,y,steps,rem = q.popleft()            \n            for x1,y1,blocked in getNei(x,y):\n                cost2 = steps+1\n                if rem-blocked >= 0 and cost2 < cost[x1][y1]:\n                    cost[x1][y1] = cost2\n                    if blocked:\n                        q.append((x1,y1,cost2,rem-blocked))\n                    else:\n                        q.appendleft((x1,y1,cost2,rem))\n        return -1 if cost[m-1][n-1] == float('inf') else cost[m-1][n-1]\n                \n    def shortestPath(self, grid, k):\n        \\\"\\\"\\\"\n        :type grid: List[List[int]]\n        :type k: int\n        :rtype: int\n        \\\"\\\"\\\"\n        dirs = [(1,0),(0,1),(-1,0),(0,-1)]\n        def getNei(x,y):\n            for dx,dy in dirs:\n                if 0<=x+dx<m and 0<=y+dy<n:\n                    yield x+dx,y+dy,grid[x+dx][y+dy]\n                \n        m,n,maxmn = len(grid),len(grid[0]), 40*40\n        costs = [[maxmn]*n for _ in range(m)]\n        costs[0][0] = 0\n        bfs = collections.deque([(0,0,0,k)])\n        while bfs:\n            x,y,cost,clears = bfs.popleft()            \n            for xn,yn,blocked in getNei(x,y):\n                newcost = cost+1\n                newclears = clears-blocked\n                if newclears >= 0 and newcost < costs[xn][yn]:\n                    costs[xn][yn] = newcost\n                    if blocked:\n                        bfs.append((xn,yn,newcost,newclears))\n                    else:\n                        bfs.appendleft((xn,yn,newcost,newclears))\n        return -1 if costs[m-1][n-1] == maxmn else costs[m-1][n-1]\n            ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # Just use BFS to record the steps and celss modified\n        # One concern is that you cannot simply record the stepped cells\n        # Because if u stepped on one cell u would not step on this again\n        # But u r using BFS, u might step on some cells because it is near the start\n        # But if u continue to walk down this path, u dont have enough modifications\n        # But there might be a path that require a detour first and then walk back on this\n        # Path, this requires step on stepped cells\n        # But if we dont record the stepped cells, it might TLE because u will running in cycles\n        # So we need to record stepped cells but can be stepped on again\n        # So we record the cells with the modifications made sofar\n        q = collections.deque()\n        if grid[0][0] == 1: k-= 1\n        q.append([0,k,0,0])\n        m,n = len(grid),len(grid[0])\n        record = set()\n        record.add((0,0,k))\n        while q:\n            l = len(q)\n            for _ in range(l):\n                step,s,x,y = q.popleft()\n                if x == m-1 and y == n-1:\n                    if grid[x][y] == 1 and s == 0:continue\n                    return step\n                for i,j in ((x+1,y),(x-1,y),(x,y+1),(x,y-1)):\n                    if 0<=i<m and 0<=j<n:\n                        if grid[i][j] == 1:\n                            if s>= 1 and (i,j,s-1) not in record:\n                                record.add((i,j,s-1))\n                                q.append([step+1,s-1,i,j])\n                        else:\n                            if (i,j,s) not in record:\n                                record.add((i,j,s))\n                                q.append([step+1,s,i,j])\n        return -1\n                \n                \n                \n                \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        visited = set()\n        mem = {}\n        MAX_NUM = float(\\\"inf\\\")\n        directions = [[0,1],[0,-1],[1,0],[-1,0]]\n        def dfs(i, j, k):\n            if i == len(grid)-1 and j == len(grid[0])-1:\n                return len(visited)\n\n            if (i,j,k) in mem:\n                return mem[(i,j,k)]\n\n            if (i, j) in visited:\n                return MAX_NUM\n\n            if i < 0 or j < 0 or  i >= len(grid) or j >= len(grid[0]):\n                return  MAX_NUM\n\n            if grid[i][j] == 1 and k == 0:\n                return MAX_NUM\n\n            if grid[i][j] == 1:\n                k -= 1\n\n            min_steps = MAX_NUM\n            visited.add((i,j))\n            for di, dj in directions:\n                min_steps = min(min_steps, dfs(i+di, j+dj, k))\n            visited.remove((i,j))\n\n            mem[(i,j,k)] = min_steps\n\n            return min_steps\n        \n        def bfs(i, j, k):\n            q = []\n            q.append((i,j,k,0))\n            visited.add((i,j,k))\n            \n            while len(q) > 0:\n                curr_i, curr_j, curr_k, depth = q.pop(0)\n                \n                if curr_i < 0 or curr_j < 0 or  curr_i >= len(grid) or curr_j >= len(grid[0]):\n                    continue\n                \n                if grid[curr_i][curr_j] == 1 and curr_k == 0:\n                    continue\n                \n                if curr_i == len(grid)-1 and curr_j == len(grid[0])-1:\n                    print(curr_k)\n                    return depth\n                \n                new_k = curr_k\n                if grid[curr_i][curr_j] == 1:\n                    new_k -= 1\n                    \n                for di, dj in directions:\n                    if (curr_i+di, curr_j+dj, new_k) not in visited:\n                        q.append((curr_i+di, curr_j+dj, new_k, depth+1))\n                        visited.add((curr_i+di, curr_j+dj,new_k))\n            return -1\n\n        return bfs(0,0,k)\n    \n#         res = dfs(0,0,k)\n#         if res == MAX_NUM:\n#             return -1\n        \n#         return res\n\n        ", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0\n     \n        queue = deque([(0, 0, k, 0)])\n        visited = set((0, 0, k))\n        directions = [(0, 1), (1, 0), (-1, 0), (0, -1)]\n        \n        while queue:\n            row, col, elim, steps = queue.popleft()\n\n            for r, c in directions:\n                new_row = row + r\n                new_col = col + c\n                if (new_row < 0 or new_row >= len(grid) or new_col < 0 or new_col >= len(grid[0])):\n                    continue    \n                if grid[new_row][new_col] == 1 and elim > 0 and (new_row, new_col, elim-1) not in visited:\n                    queue.append((new_row, new_col, elim-1, steps + 1))\n                    visited.add((new_row, new_col, elim-1))\n                if grid[new_row][new_col] == 0 and (new_row, new_col, elim) not in visited:\n                    if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n                        return steps+1\n                    queue.append((new_row, new_col, elim, steps + 1))\n                    visited.add((new_row, new_col, elim))\n        \n        return -1\n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        m,n = len(grid),len(grid[0])\n        frontier = collections.deque([(0,0,k,0)])\n        seen = {(0,0,k)}\n        # print(m,n)\n        while frontier:\n            i,j,d,steps = frontier.popleft()\n            # print('Cur - ',i,j,d,steps)\n            if i==m-1 and j==n-1: return steps\n            for a,b in [(1,0),(0,1),(-1,0),(0,-1)]:\n                r,c = i+a, j+b\n                if 0<=r<m and 0<=c<n and (r,c,d-grid[r][c]) not in seen and d>=grid[r][c]:\n                    seen.add((r,c,d-grid[r][c]))\n                    frontier.append((r,c,d-grid[r][c],steps+1))\n        \n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def inBounds(x, y):\n            if x < 0:\n                return False\n            elif y < 0:\n                return False\n            elif x >= len(grid[0]):\n                return False\n            elif y >= len(grid):\n                return False\n            \n            return True\n        \n        target = (len(grid[0])-1, len(grid)-1)\n        \n        queue = deque([(0, 0, k, 0)])\n        \n        visited = set([(0, 0, k)])\n        \n        if target == (0, 0):\n            return 0\n        \n        \n        while queue:\n            x, y, k, dist = queue.popleft()\n            \n            for dx, dy in [(1, 0), (0, 1), (-1, 0), (0, -1)]:     \n                if (x+dx, y+dy) == target:\n                    return dist + 1\n\n                if not inBounds(x+dx, y+dy):\n                    continue\n                \n                if grid[y+dy][x+dx] == 0 and (x+dx, y+dy, k) not in visited:\n                    visited.add((x+dx, y+dy, k))\n                    queue.append((x+dx, y+dy, k, dist+1))\n                elif k > 0 and (x+dx, y+dy, k-1) not in visited:\n                    visited.add((x+dx, y+dy, k-1))\n                    queue.append((x+dx, y+dy, k-1, dist+1))\n                    \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        seen = set()\n        seen.add((0,0,k))\n        q = deque([(0,0,k,0)])\n                \n        while q:\n            x,y, remaining, moves = q.popleft()\n            \n            if x == len(grid)-1 and y == len(grid[0])-1: return moves\n            \n            for new_x, new_y in [[x-1,y],[x+1,y],[x,y-1],[x,y+1]]:\n                if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[0]):\n                    if grid[new_x][new_y] == 1 and (new_x,new_y,remaining-1) not in seen and remaining > 0:\n                        seen.add((new_x,new_y,remaining-1))\n                        q.append((new_x, new_y, remaining-1, moves+1))\n                        \n                    elif grid[new_x][new_y] == 0 and (new_x,new_y,remaining) not in seen:\n                        seen.add((new_x,new_y,remaining))\n                        q.append((new_x, new_y, remaining, moves+1))\n        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # visited = set()\n        # visited.add((0, 0, k))\n        # candidates = deque()\n        # candidates.append((0, 0, 0, k))\n        # if len(grid) == 1 and len(grid[0]) == 1: return 0\n        # while len(candidates) > 0:\n        #     ci, cj, steps, ck = candidates.popleft()\n        #     if ci == len(grid) -1 and cj == len(grid[0]) - 1:\n        #         return steps\n        #     for x, y in [[-1, 0], [1, 0], [0, -1], [0, 1]]:\n        #         ni, nj = ci + x, cj + y\n        #         if ni < 0 or nj < 0 or ni >= len(grid) or nj >= len(grid[0]): \n        #             continue\n        #         if (ni, nj, ck) in visited: \n        #             continue\n        #         if grid[ni][nj] == 1 and ck > 0:\n        #             candidates.append((ni, nj, steps+1, ck-1))\n        #             visited.add((ni, nj, ck-1))\n        #         elif grid[ni][nj] == 0:\n        #             candidates.append((ni, nj, steps+1, ck))\n        #             visited.add((ni, nj, ck))\n        # return -1\n    \n        rows = len(grid)\n        cols = len(grid[0])\n\\t\\t# Directions we'll use to change our location (down, up, right, left).\n        directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        # We'll use a deque for our BFS traversal.\n        q = collections.deque([])\n\\t\\t# Append our starting details to the q.\n\\t\\t# (row, col, steps, k)\n        q.append((0, 0, 0, k))\n\\t\\t# Use a set (O(1) lookup) to track the locations we've visited to avoid revisiting.\n        seen = set()\n        seen.add((0, 0 , k))\n        while q:\n\\t\\t    # Pop the next location from the q.\n            r, c, steps, rk = q.popleft()\n\\t\\t\\t# If we're at the finish location return the steps, given BFS this will be\n\\t\\t\\t# guaranteed to be the first to hit this condition.\n            if r == rows-1 and c == cols - 1:\n                return steps\n\\t\\t\\t# Otherwise we'll keep travelling throught the grid in our 4 directions.\n            else:\n                for y, x in directions:\n                    nr = r + y\n                    nc = c + x\n\\t\\t\\t\\t\\t# If the new location is on the board and has not been visited.\n                    if nr >= 0 and nr < rows and nc >= 0 and nc < cols and (nr, nc, rk) not in seen:\n\\t\\t\\t\\t\\t    # If it's a blocker but we still have k left, we'll go there and k -= 1.\n                        if grid[nr][nc] == 1 and rk > 0:\n                            seen.add((nr, nc, rk))\n                            q.append((nr, nc, steps + 1, rk - 1))\n\\t\\t\\t\\t\\t\\t# Otherwise continue on  if it's a 0 - free location.\n                        elif grid[nr][nc] == 0:\n                            seen.add((nr, nc, rk))\n                            q.append((nr, nc, steps + 1, rk))\n\\t\\t# If we don't hit the end in our traversal we know it's not possible.\n        return -1\n            \n\n        ", "from collections import deque \n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: \n            return -1 \n        rows = len(grid)\n        cols = len(grid[0])\n        visited = {(0, 0, 0)}\n        \n        queue = deque()\n        queue.append((0, 0, 0))\n        steps = 0\n        \n        while queue: \n            newqueue = deque()\n            for (x, y, r) in queue: \n                if x == rows - 1 and y == cols - 1:\n                    return steps\n                for (i, j) in [(x, y - 1), (x, y+1), (x+1, y), (x-1, y)]:\n                    if i >= 0 and i < rows and j >= 0 and  j < cols: \n                        if grid[i][j] == 0 and (i, j, r) not in visited:\n                            newqueue.append((i, j, r))\n                            visited.add((i, j, r))\n                        elif grid[i][j] == 1 and r+1 <= k and (i, j, r+1) not in visited: \n                            newqueue.append((i, j, r+1))\n                            visited.add((i, j, r+1))\n            queue = newqueue\n            steps += 1\n        return -1 \n            \n#         if not grid:\n#             return -1\n#         rows = len(grid)\n#         cols = len(grid[0])\n        \n#         #dist = grid.copy()\n#         #dist[0][0] = 0\n#         dist = [[0 for j in range(cols)] for i in range(rows)]\n#         queue = deque() \n#         queue.append((0, 0, 0))\n#         #queue = [(0, 0, 0)]\n#         while queue:\n#             (x, y, r) = queue.popleft()\n            \n#             if y > 0 and grid[x][y-1] >= 0:\n#                 if grid[x][y-1] == 0:\n#                     queue.append((x, y-1, r))\n#                     dist[x][y-1] = dist[x][y] + 1\n#                 if grid[x][y-1] == 1 and r+1 <= k:\n#                     queue.append((x, y-1, r + 1))\n#                     dist[x][y-1] = dist[x][y] + 1\n#             if x > 0 and grid[x-1][y] >= 0:\n#                 if grid[x-1][y] == 0:\n#                     queue.append((x-1, y, r))\n#                     dist[x-1][y] = dist[x][y] + 1\n#                 if grid[x-1][y] == 1 and r+1 <= k:\n#                     queue.append((x-1, y, r + 1))\n#                     dist[x-1][y] = dist[x][y] + 1\n#             if x < rows -1 and grid[x+1][y] >= 0:\n#                 if grid[x+1][y] == 0:\n#                     queue.append((x+1, y, r))\n#                     dist[x+1][y] = dist[x][y] + 1\n#                 if grid[x+1][y] == 1 and r+1 <= k:\n#                     queue.append((x+1, y, r + 1))\n#                     dist[x+1][y] = dist[x][y] + 1\n#             if y < cols-1 and grid[x][y+1] >= 0:\n#                 if grid[x][y+1] == 0:\n#                     queue.append((x, y+1, r))\n#                     dist[x][y+1] = dist[x][y] + 1\n#                 if grid[x][y+1] == 1 and r+1 <= k:\n#                     queue.append((x, y+1, r + 1))\n#                     dist[x][y+1] = dist[x][y] + 1\n#             grid[x][y] = -1\n#         print(dist)\n#         if grid[rows-1][cols-1] != -1: \n#             return -1\n#         else:\n#             return dist[rows-1][cols-1]\n", "from collections import defaultdict, deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def getNei(x,y):\n            for dx,dy in dirs:\n                xn,yn = x+dx,y+dy\n                if 0<=xn<m and 0<=yn<n:\n                    yield xn,yn,grid[xn][yn]\n                \n        dirs = [(1,0),(0,1),(-1,0),(0,-1)]\n        m,n,maxmn = len(grid),len(grid[0]), float('inf')\n        costs = [[maxmn]*n for _ in range(m)]\n        costs[0][0] = 0\n        bfs = collections.deque([(0,0,0,k)])\n        while bfs:\n            x,y,cost,clears = bfs.popleft()            \n            for xn,yn,blocked in getNei(x,y):\n                newcost = cost+1\n                newclears = clears-blocked\n                if newclears >= 0 and newcost < costs[xn][yn]:\n                    costs[xn][yn] = newcost\n                    if blocked:\n                        bfs.append((xn,yn,newcost,newclears)) # dfs stack\n                    else:\n                        bfs.appendleft((xn,yn,newcost,newclears)) # bfs queue\n        return -1 if costs[m-1][n-1] == maxmn else costs[m-1][n-1]", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        q = deque([(0, 0, k, 0)])\n        visited = set([(0, 0, k)])\n        \n        def move(i, j, k):\n            for di, dj in ((-1, 0), (1, 0), (0, -1), (0, 1)):\n                ni, nj = i + di, j + dj\n                if 0 <= ni < m and 0 <= nj < n:\n                    nk = k - grid[ni][nj]\n                    if nk >= 0 and (ni, nj, nk) not in visited:\n                        yield ni, nj, nk\n        while q:\n            i, j, k, s = q.pop()\n            if i == m - 1 and j == n - 1:\n                return s\n            \n            for ni, nj, nk in move(i, j, k):\n                visited.add((ni, nj, nk))\n                q.appendleft((ni, nj, nk, s + 1))\n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid, k: int) -> int:\n        m,n = len(grid),len(grid[0])\n        num_obs,obs = 0,{}\n        for i in range(m):\n            for j in range(n):\n                if grid[i][j]==1:\n                   \n                    num_obs+=1\n        if num_obs<=k: return m+n-2\n        q = [(0,0,0,k)]\n        visited = set()\n        while q:\n            l = len(q)\n            for _ in range(l):\n                step,i,j,rem = q.pop(0)\n                if i==m-1 and j==n-1: \n                    return step\n                if (i,j,rem) in visited: continue\n                visited.add((i,j,rem))\n                for x,y in ((i-1,j),(i+1,j),(i,j-1),(i,j+1)):\n                    if 0<=x<m and 0<=y<n:\n                        if grid[x][y]==0:\n                            q.append((step+1,x,y,rem))\n                        elif grid[x][y]==1 and rem>0:                        \n                            q.append((step+1,x,y,rem-1))\n        return -1 \n        \n", "import math\nimport collections\nimport heapq\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        \n        def neighbors(x, y):\n            for dx, dy in [(-1,0), (1, 0), (0, -1), (0, 1)]:\n                if x+dx >= 0 and x+dx < m and y+dy >= 0 and y+dy < n:\n                    yield x+dx, y+dy\n        \n        bfs = collections.deque([(0, 0, 0, k)])\n        visited = set()\n        \n        while bfs:\n            i, j, cost, rems = bfs.popleft()\n            if (i == m-1) and (j == n-1): return cost\n\n            if (i, j, rems) in visited: continue\n            visited.add((i, j, rems))\n            \n                        \n            for x, y in neighbors(i, j):\n                if grid[x][y] == 1 and rems == 0: continue\n                if grid[x][y] == 1:\n                    bfs.append((x, y, cost+1, rems-1))\n                else:\n                    bfs.append((x,y,cost+1, rems))\n                    \n        return -1", "# from collections import deque\n# class Solution:\n#     def shortestPath(self, grid: List[List[int]], k: int) -> int:\n#         if len(grid) == 1 and len(grid[0]) == 1:\n#             return 0\n\n#         queue = deque([(0,0,k,0)])\n#         visited = set([(0,0,k)])\n\n#         if k > (len(grid)-1 + len(grid[0])-1):\n#             return len(grid)-1 + len(grid[0])-1\n\n#         while queue:\n#             row, col, eliminate, steps = queue.popleft()\n#             for new_row, new_col in [(row-1,col), (row,col+1), (row+1, col), (row, col-1)]:\n#                 if (new_row >= 0 and\n#                     new_row < len(grid) and\n#                     new_col >= 0 and\n#                     new_col < len(grid[0])):\n#                     if grid[new_row][new_col] == 1 and eliminate > 0 and (new_row, new_col, eliminate-1) not in visited:\n#                         visited.add((new_row, new_col, eliminate-1))\n#                         queue.append((new_row, new_col, eliminate-1, steps+1))\n#                     if grid[new_row][new_col] == 0 and (new_row, new_col, eliminate) not in visited:\n#                         if new_row == len(grid)-1 and new_col == len(grid[0])-1:\n#                             return steps+1\n#                         visited.add((new_row, new_col, eliminate))\n#                         queue.append((new_row, new_col, eliminate, steps+1))\n\n#         return -1\nfrom collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque([(0,0,k,0)])\n        rows = len(grid)\n        cols = len(grid[0])\n        ans = float('inf')\n        vis = {(0,0,k): 1}\n        while len(queue) > 0:\n            # print(queue)\n            x, y, rem, depth = queue.popleft()\n            # print(x,y,rem,depth)\n            if x == rows - 1 and y == cols - 1:\n                return depth\n            for i, j in [[1,0], [0,1], [-1,0], [0,-1]]:\n                i += x\n                j += y\n                if i < 0 or i >= rows or j < 0 or j >= cols or (i,j, rem) in vis or (grid[i][j] == 1 and rem <= 0):\n                    continue\n                elif grid[i][j] == 0 and (i,j,rem) not in vis:\n                    vis[(i,j,rem)] = 1\n                    queue.append((i,j,rem,depth+1))\n                elif grid[i][j] == 1 and rem > 0 and (i,j, rem-1) not in vis:\n                    vis[(i,j,rem-1)] = 1\n                    queue.append((i,j,rem-1,depth+1))\n        if ans == float('inf'):\n            return -1\n        return ans", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        visited = set()\n        visited.add((0, 0, k))\n        candidates = collections.deque([])\n        candidates.append((0, 0, 0, k))\n        if len(grid) == 1 and len(grid[0]) == 1: return 0\n        while len(candidates) > 0:\n            ci, cj, steps, ck = candidates.popleft()\n            if ci == len(grid) -1 and cj == len(grid[0]) - 1:\n                return steps\n            for x, y in [[-1, 0], [1, 0], [0, -1], [0, 1]]:\n                ni, nj = ci + x, cj + y\n                if ni < 0 or nj < 0 or ni >= len(grid) or nj >= len(grid[0]): \n                    continue\n                if (ni, nj, ck) in visited: \n                    continue\n                if grid[ni][nj] == 1 and ck > 0:\n                    candidates.append((ni, nj, steps+1, ck-1))\n                    visited.add((ni, nj, ck))\n                elif grid[ni][nj] == 0:\n                    candidates.append((ni, nj, steps+1, ck))\n                    visited.add((ni, nj, ck))\n        return -1\n    \n#         rows = len(grid)\n#         cols = len(grid[0])\n# \\t\\t# Directions we'll use to change our location (down, up, right, left).\n#         directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n#         # We'll use a deque for our BFS traversal.\n#         q = collections.deque([])\n# \\t\\t# Append our starting details to the q.\n# \\t\\t# (row, col, steps, k)\n#         q.append((0, 0, 0, k))\n# \\t\\t# Use a set (O(1) lookup) to track the locations we've visited to avoid revisiting.\n#         seen = set()\n#         seen.add((0, 0))\n#         while q:\n# \\t\\t    # Pop the next location from the q.\n#             r, c, steps, rk = q.popleft()\n# \\t\\t\\t# If we're at the finish location return the steps, given BFS this will be\n# \\t\\t\\t# guaranteed to be the first to hit this condition.\n#             if r == rows-1 and c == cols - 1:\n#                 return steps\n# \\t\\t\\t# Otherwise we'll keep travelling throught the grid in our 4 directions.\n#             else:\n#                 for y, x in directions:\n#                     nr = r + y\n#                     nc = c + x\n# \\t\\t\\t\\t\\t# If the new location is on the board and has not been visited.\n#                     if nr >= 0 and nr < rows and nc >= 0 and nc < cols and (nr, nc, rk) not in seen:\n# \\t\\t\\t\\t\\t    # If it's a blocker but we still have k left, we'll go there and k -= 1.\n#                         if grid[nr][nc] == 1 and rk > 0:\n#                             seen.add((nr, nc, rk))\n#                             q.append((nr, nc, steps + 1, rk - 1))\n# \\t\\t\\t\\t\\t\\t# Otherwise continue on  if it's a 0 - free location.\n#                         elif grid[nr][nc] == 0:\n#                             seen.add((nr, nc, rk))\n#                             q.append((nr, nc, steps + 1, rk))\n# \\t\\t# If we don't hit the end in our traversal we know it's not possible.\n#         return -1\n            \n\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # bfs but consider a cell visited only when same (position, k value)\n        \n        n = len(grid)\n        if n == 0:\n            return 0\n        \n        m = len(grid[0])\n        \n        visited = set()\n        q = collections.deque([((0,0),k,0)])\n        \n        while q:\n            (r,c), k_left, dist = q.popleft()\n            if ((r,c),k_left) in visited:\n                continue\n                \n            visited.add(((r,c),k_left))\n            \n            if r == n-1 and c == m-1:\n                return dist\n            \n            # add neighbors\n            for dr,dc in [(1,0),(-1,0),(0,1),(0,-1)]:\n                # if valid cell and either the cell is traversable (0) or we have eliminations remaining, \n                # traverse the cell\n                if (0 <= r+dr < n and 0 <= c+dc < m) and (grid[r+dr][c+dc] == 0 or k_left > 0):\n                    q.append(((r+dr,c+dc), k_left - grid[r+dr][c+dc], dist+1))\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        if m * n == 1:\n            return 0\n        dp = [[[float('inf')] * (k + 1) for _ in range(n)] for _ in range(m)]\n        dp[0][0][k] = 0\n        q = deque([(0, 0, k)])\n        def move(i, j, k):\n            for di, dj in ((-1, 0), (1, 0), (0, -1), (0, 1)):\n                ni, nj = i + di, j + dj\n                if 0 <= ni < m and 0 <= nj < n and k >= grid[ni][nj]:\n                    yield ni, nj, k - grid[ni][nj]\n        while q:\n            i, j, k = q.pop()\n            for ni, nj, nk in move(i, j, k):\n                if ni == m -1 and nj == n -1:\n                    return dp[i][j][k] + 1\n                \n                if dp[i][j][k] + 1 < dp[ni][nj][nk]:\n                    dp[ni][nj][nk] = dp[i][j][k] + 1\n                    q.appendleft((ni, nj, nk))\n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if grid[0][0] == 1 and k == 0:\n            return -1\n        \n        m, n = len(grid), len(grid[0])\n        if grid[0][0]:\n            k -= 1\n        qe = collections.deque([(0, 0, 0, k)])\n        \n        visited = set()\n        visited.add((0, 0, k))\n        \n        dr = [[0,1],[0,-1],[1,0],[-1,0]]\n        \n        while qe:\n            i, j, step, k = qe.popleft()\n            if i == m-1 and j == n-1:\n                return step\n            \n            for x, y in dr:\n                i1, j1 = i + x, j + y\n                if i1 < 0 or i1 >= m or j1 < 0 or j1 >= n:\n                    continue\n                if grid[i1][j1] == 1 and k == 0:\n                    continue\n                if grid[i1][j1] == 1 and k >= 1 and (i1, j1, k-1) not in visited:\n                    visited.add((i1, j1, k-1))\n                    qe.append((i1, j1, step+1, k-1))\n                if grid[i1][j1] == 0 and k >= 0 and (i1, j1, k) not in visited:\n                    if i1 == m-1 and j1 == n-1:\n                        return step+1\n                    visited.add((i1, j1, k))\n                    qe.append((i1, j1, step+1, k))\n                \n                        \n        return -1", "from queue import Queue\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        q = Queue()\n        q.put((0,0,0,0))\n        visited = {}\n        mins = float('inf')\n        nr = len(grid)\n        nc = len(grid[0])\n        \n        \n        \n        while q.qsize()>0:\n            \n            i,j,obs,count = q.get()\n            \n            if obs>k:\n                continue\n            \n            if i==nr-1 and j==nc-1:\n                mins = min(mins,count)\n            \n            if (i,j) not in visited or ((i,j) in visited and visited[(i,j)]>obs):\n                visited[(i,j)]=obs\n                for x,y in [(i-1,j),(i+1,j),(i,j-1),(i,j+1)]:\n                    if 0<=x<nr and 0<=y<nc:\n                        if grid[x][y]==1:\n                            q.put((x,y,obs+1,count+1))\n                        else:\n                            q.put((x,y,obs,count+1))\n        if mins==float('inf'):\n            return -1\n        \n        return mins\n                \n            \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        from collections import deque\n        m, n = len(grid), len(grid[0])\n        queue = deque()\n        queue.append(((0, 0, 0, 0)))\n        directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]\n        visited = set([(0, 0 , 0)])\n\n        \n        while queue:\n            x, y, elim, path = queue.popleft()\n            if x==m-1 and y==n-1: return path\n            for dx, dy in directions:\n                nx, ny = x+dx, y+dy\n                if 0<=nx<m and 0<=ny<n:\n                    if grid[nx][ny] == 0 and (nx, ny, elim) not in visited:\n                        queue.append((nx, ny, elim, path + 1))\n                        visited.add((nx,ny, elim))\n                    if grid[nx][ny] == 1 and elim<k and (nx, ny, elim-1) not in visited:\n                        queue.append((nx, ny, elim+1, path + 1))\n                        visited.add((nx,ny, elim+1))\n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def valid(i,j):\n            if i>=0 and j>=0 and i<len(grid) and j<len(grid[0]):\n                return True\n            return False\n        \n        dq=deque([(0,0,k,0)])\n        visited=set()\n        res=math.inf\n        \n        def search(i,j,k,l):\n            if (i,j,k) in visited:\n                return False\n            visited.add((i,j,k))\n            nonlocal res\n            if k<0:\n                return False\n            if i==len(grid)-1 and j==len(grid[0])-1:\n                res=l\n                return True\n            for di,dj in [(1,0),(0,1),(-1,0),(0,-1)]:\n                if valid(i+di,j+dj):\n                    next_k=k if grid[i+di][j+dj]==0 else k-1\n                    dq.append((i+di,j+dj,next_k,l+1))\n            \n            return False\n        while dq:\n            i,j,k,l=dq.popleft()\n            if search(i,j,k,l):\n                break\n        return res if res!=math.inf else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q=collections.deque([[0,0,k]])\n        res,m,n=0,len(grid),len(grid[0])\n        seen=set()\n        dirs=[[0,1],[0,-1],[1,0],[-1,0]]\n        while q:\n            for i in range(len(q)):\n                cur=q.popleft()\n                if cur[0]==m-1 and cur[1]==n-1:\n                    return res\n                for di in dirs:\n                    ni=cur[0]+di[0]\n                    nj=cur[1]+di[1]\n                    if ni<0 or ni>=m or nj<0 or nj>=n:\n                        continue\n                    ha=str(ni)+\\\",\\\"+str(nj)+\\\",\\\"+str(cur[2])\n                    if ha not in seen:\n                        if grid[ni][nj]==0:\n                            seen.add(ha)\n                            q.append([ni,nj,cur[2]])\n                        else:\n                            if cur[2]>0:\n                                seen.add(ha)\n                                q.append([ni,nj,cur[2]-1])\n            res+=1\n            \n        return -1\n            ", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def valid(i,j):\n            if i>=0 and j>=0 and i<len(grid) and j<len(grid[0]):\n                return True\n            return False\n        \n        dq=deque([(0,0,k,0)])\n        visited=set()\n        res=math.inf\n        \n        def search(i,j,k,l):\n            if (i,j,k) in visited:\n                return False\n            visited.add((i,j,k))\n            nonlocal res\n            if k<0:\n                return False\n            if i==len(grid)-1 and j==len(grid[0])-1:\n                res=l\n                return True\n            for di,dj in [(1,0),(0,1),(-1,0),(0,-1)]:\n                if valid(i+di,j+dj):\n                    next_k=k if grid[i+di][j+dj]==0 else k-1\n                    dq.append((i+di,j+dj,next_k,l+1))\n            \n            return False\n        while dq:\n            i,j,k,l=dq.popleft()\n            if search(i,j,k,l):\n                break\n        return res if res!=math.inf else -1\n", "class Solution:\n    \n    @staticmethod\n    def get_neis(x, y):\n        return [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]\n\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n\n        m = len(grid)\n        n = len(grid[0])\n        k = min(k, m + n)\n        grid_mem = [[[math.inf] * n for _ in range(m)] for ki in range(k+1)]\n        grid_mem[0][0][0] = 0\n        visited = {(0, 0)}\n        q = collections.deque([(0, 0)])\n\n        while len(q) > 0:\n            i, j = q.popleft()\n            for x, y in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:\n                if 0 <= x < m and 0 <= y < n and (x, y) not in visited and grid[x][y] == 0:\n                    grid_mem[0][x][y] = grid_mem[0][i][j] + 1\n                    visited.add((x, y))\n                    q.append((x, y))\n\n        for ki in range(1, k+1):\n            grid_mem[ki][0][0] = 0\n            visited = {(0, 0)}\n            q = collections.deque([(0, 0)])\n            while len(q) > 0:\n                i, j = q.popleft()\n                for x, y in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:\n                    if 0 <= x < m and 0 <= y < n and (x, y) not in visited:\n                        level = ki if grid[x][y] == 0 else ki-1\n                        path = math.inf\n                        for x2, y2 in self.get_neis(x, y):\n                            if 0 <= x2 < m and 0 <= y2 < n:\n                                path = min(path, grid_mem[level][x2][y2])\n                        grid_mem[ki][x][y] = path+1\n                        visited.add((x, y))\n                        q.append((x, y))\n\n        if grid_mem[-1][-1][-1] < math.inf:\n            return grid_mem[-1][-1][-1]\n        else:\n            return -1\n", "from typing import List\n\n\nclass Solution:\n    def __init__(self):\n        self.dx = [1, -1, 0, 0]\n        self.dy = [0, 0, 1, -1]\n\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        res = -1\n        m = len(grid)\n        n = len(grid[0])\n        q = [(0, 0, 0, 0)]\n        head, tail = 0, 1\n        visited = set()\n        while head < tail:\n            ci, cj, uk, d = q[head]\n            head += 1\n            if ci == m-1 and cj == n-1:\n                res = d\n                break\n            else:\n                for i in range(0, 4):\n                    ni = ci + self.dx[i]\n                    nj = cj + self.dy[i]\n                    if 0 <= ni < m and 0 <= nj < n:\n                        if grid[ni][nj] == 1:\n                            if uk+1 <= k and (ni, nj, uk+1) not in visited:\n                                visited.add((ni, nj, uk+1))\n                                q.append((ni, nj, uk+1, d+1))\n                                tail += 1\n                        else:\n                            if (ni, nj, uk) not in visited:\n                                visited.add((ni, nj, uk))\n                                q.append((ni, nj, uk, d+1))\n                                tail += 1\n        return res\n        \n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def valid(i,j):\n            if i>=0 and j>=0 and i<len(grid) and j<len(grid[0]):\n                return True\n            return False\n        \n        dq=deque([(0,0,k,0)])\n        visited=set()\n        res=math.inf\n        \n        def search(i,j,k,l):\n            if (i,j,k) in visited:\n                return False\n            nonlocal res\n            if k<0:\n                return False\n            if i==len(grid)-1 and j==len(grid[0])-1:\n                res=l\n                return True\n            for di,dj in [(1,0),(0,1),(-1,0),(0,-1)]:\n                if valid(i+di,j+dj):\n                    next_k=k if grid[i+di][j+dj]==0 else k-1\n                    dq.append((i+di,j+dj,next_k,l+1))\n            visited.add((i,j,k))\n            return False\n        while dq:\n            i,j,k,l=dq.popleft()\n            if search(i,j,k,l):\n                break\n        return res if res!=math.inf else -1\n", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def at(point):\n            x, y = point\n            return grid[y][x]\n        \n        def valid(point):\n            x, y = point\n            return (0 <= y < len(grid) and 0 <= x < len(grid[y]))\n        \n        def neighbors(point):\n            x, y = point\n            candidates = [\n                (x, y-1),\n                (x+1, y),\n                (x, y+1),\n                (x-1, y)\n            ]\n            \n            for candidate in candidates:\n                if valid(candidate):\n                    yield(candidate)\n        \n        def moves(point, remaining):\n            for neighbor in neighbors(point):\n                if at(neighbor) == 1 and remaining > 0:\n                    yield (neighbor, remaining-1)\n                elif at(neighbor) == 0:\n                    yield (neighbor, remaining)\n\n                    \n        start = ((0, 0), k)\n        \n        prev = {\n            start: None\n        }\n        \n        def path_length(node):\n            length = 0\n            while node:\n                #print(node)\n                length += 1\n                node = prev[node]\n            return length\n        \n        frontier = deque([start])\n        \n        \n        \n        while frontier:\n            point, remaining = frontier.popleft()\n            x, y = point\n            if y == len(grid) - 1 and x == len(grid[y]) - 1:\n                return path_length((point, remaining)) - 1\n            \n            for move in moves(point, remaining):\n                if move not in prev:\n                    frontier.append(move)\n                    prev[move] = (point, remaining)\n        \n        return -1\n                \n                \n            \n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        move = [(0,1), (1,0), (0,-1), (-1,0)]\n        visited = set([])\n        q = deque([(0,0,0,k)])\n        while q:\n            r, c, cur, cur_k = q.popleft()\n            visited.add((r,c,cur_k))\n            if r == m-1 and c == n-1:\n                return cur\n            for dx, dy in move:\n                row, col = r+dy, c+dx\n                if 0<= row < m and 0 <= col < n:\n                \n                    if grid[row][col] == 1 and cur_k > 0 and \\\\\n                    (row, col, cur_k-1) not in visited:\n                        q.append((row, col, cur+1, cur_k-1))\n                        visited.add((row, col, cur_k-1))\n                    if grid[row][col] == 0 and (row, col, cur_k) not in visited:\n                        q.append((row, col, cur+1, cur_k))\n                        visited.add((row, col, cur_k))\n                        \n        \n        return -1", "# https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/discuss/451787/Python-O(m*n*k)-BFS-Solution-with-Explanation\n\nfrom collections import deque\n\ndef is_valid_cell(row, col, rows, cols):\n    return 0 <= row < rows and 0 <= col < cols\n\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # do the normal BFS but add the parameter k for eleminations\n        queue = deque()\n        visited = set()\n        \n        rows , cols = len(grid), len(grid[0])\n        start_row, start_col = 0, 0\n        end_row, end_col = rows - 1, cols - 1\n        \n        # queue tuple will look like (row, col, eliminations, steps)\n        queue.append((start_row, start_col, k, 0))\n        # visited/seen tuple will look like (row, col, eliminations)\n        visited.add((start_row, start_col, k))\n        \n        # directions\n        directions = [(1, 0), (0, 1), (0, -1), (-1, 0)]\n        \n        while queue:\n            row, col, eliminations, steps = queue.popleft()\n            # destination reached\n            if row == end_row and col == end_col:\n                return steps\n            \n            for dr, dc in directions:\n                r, c = row + dr, col + dc\n                if not is_valid_cell(r, c, rows, cols):\n                    continue\n                # hitting obstacle\n                if grid[r][c] == 1 and eliminations > 0 and (r, c, eliminations - 1) not in visited:\n                    visited.add((r, c, eliminations - 1))\n                    queue.append((r, c, eliminations - 1, steps + 1))\n                \n                # not hitting obstacle\n                if grid[r][c] == 0 and (r, c, eliminations) not in visited:\n                    visited.add((r, c, eliminations))\n                    queue.append((r, c, eliminations, steps + 1))\n        \n        return -1\n            \n            \n            \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n,m = len(grid),len(grid[0])\n        # cost, used, i, j\n        heap = [(0,0,0,0)]\n        seen = set()\n        while heap:\n            c,used,i,j = heapq.heappop(heap)\n            if (i,j,used) in seen:\n                continue\n            if i==n-1 and j==m-1:\n                return c\n            seen.add((i,j,used))\n            for ni,nj in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                if 0<=ni<n and 0<=nj<m and used+grid[ni][nj]<=k and (ni,nj,used+grid[ni][nj]) not in seen:\n                    heapq.heappush(heap,(c+1,used+grid[ni][nj],ni,nj))\n        \n        return -1\n", "class Solution(object):\n          \n    def shortestPath(self, grid, k):\n        \\\"\\\"\\\"\n        :type grid: List[List[int]]\n        :type k: int\n        :rtype: int\n        \\\"\\\"\\\"\n        dirs = [(1,0),(0,1),(-1,0),(0,-1)]\n        def getNei(x,y):\n            for dx,dy in dirs:\n                if 0<=x+dx<m and 0<=y+dy<n:\n                    yield x+dx,y+dy,grid[x+dx][y+dy]\n                \n        m,n,maxmn = len(grid),len(grid[0]), float('inf')\n        costs = [[maxmn]*n for _ in range(m)]\n        costs[0][0] = 0\n        bfs = collections.deque([(0,0,0,k)])\n        while bfs:\n            x,y,cost,clears = bfs.popleft()            \n            for xn,yn,blocked in getNei(x,y):\n                newcost = cost+1\n                newclears = clears-blocked\n                if newclears >= 0 and newcost < costs[xn][yn]:\n                    costs[xn][yn] = newcost\n                    if blocked:\n                        bfs.append((xn,yn,newcost,newclears))\n                    else:\n                        bfs.appendleft((xn,yn,newcost,newclears))\n        return -1 if costs[m-1][n-1] == maxmn else costs[m-1][n-1]\n            ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid)==1 and len(grid[0]) == 1:\n            return 0\n        q = []\n        visited = set((0,0,0))\n        heapq.heappush(q,(0,0,(0,0)))\n        while(len(q)>0):\n            curr = heapq.heappop(q)\n            if curr[2] == (len(grid)-1,len(grid[0])-1):\n                return curr[0]\n            else:\n                for dx,dy in [(-1,0),(1,0),(0,-1),(0,1)]:\n                    new_x = curr[2][0]+dx\n                    new_y = curr[2][1]+dy\n                    if new_x>=0 and new_x<len(grid) and new_y>=0 and new_y<len(grid[0]):\n                        if grid[new_x][new_y] == 1:\n                            if (curr[1]+1,new_x,new_y) not in visited and curr[1]+1<=k:\n                                heapq.heappush(q,(curr[0]+1,curr[1]+1,(new_x,new_y)))\n                                visited.add((curr[1]+1,new_x,new_y))\n                        else:\n                            if (curr[1],new_x,new_y) not in visited:\n                                heapq.heappush(q,(curr[0]+1,curr[1],(new_x,new_y)))\n                                visited.add((curr[1],new_x,new_y))\n        return -1          \n        \n        # if len(grid)==1 and len(grid[0]) == 1:\n        #     return 0\n        # q = collections.deque()\n        # visited = set((0,0,0))\n        # q.append(((0,0),0))\n        # level = 1\n        # while(len(q)>0):\n        #     length = len(q)\n        #     for i in range(length):\n        #         curr = q.popleft()\n        #         for dx,dy in [(-1,0),(1,0),(0,-1),(0,1)]:\n        #             new_x = curr[0][0]+dx\n        #             new_y = curr[0][1]+dy\n        #             if new_x>=0 and new_x<len(grid) and new_y>=0 and new_y<len(grid[0]):\n        #                 obs = curr[1]\n        #                 if grid[new_x][new_y] == 1:\n        #                     obs+=1\n        #                 if (new_x,new_y,obs) not in visited and obs<=k:\n        #                         visited.add((new_x,new_y, obs))\n        #                         q.append(((new_x,new_y),obs))\n        #                         if new_x == len(grid)-1 and new_y == len(grid[0])-1:\n        #                             return level\n        #     level+=1\n        # return -1\n", "from collections import deque, namedtuple\n\nStep = namedtuple('Step', [\\\"row\\\", \\\"col\\\", \\\"step\\\"])\n\nclass Solution:\n    def shortestPath(self, m: List[List[int]], k: int) -> int:\n        queue = deque()\n        queue.append(Step(row=0,col=0,step=0))\n        visited = set([Step(row=0,col=0,step=0)])\n\n        level = 0\n\n        directions = [(1,0),(-1,0),(0,1),(0,-1)]\n        destX, destY = len(m) - 1, len(m[0]) - 1\n\n        while len(queue):\n            for _ in range(len(queue)):\n                posX, posY, step = queue.popleft()\n                if (posX, posY) == (destX, destY):\n                    return level\n                for x, y in directions:\n                    newX, newY = x + posX, y + posY\n                    if (0 <= newX < len(m)) and (0 <= newY < len(m[0])):\n\n                        if m[newX][newY] == 1:\n                            new_step = step + 1\n                            next_move = Step(row=newX,col=newY,step=new_step)\n                            if next_move not in visited and new_step <= k:\n                                queue.append(next_move)\n                                visited.add(next_move)\n                        else:\n                            next_move = Step(row=newX,col=newY,step=step)\n                            if next_move not in visited:\n                                queue.append(next_move)\n                                visited.add(next_move)\n            level += 1\n\n        return -1\n        ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \\\"\\\"\\\"\n        (x, y, 3)\n        \n        (x1, y1, 1) (x2, y2, 1)\n        \\\"\\\"\\\"\n        def get_neighs(cell, grid):\n            M = len(grid)\n            N = len(grid[0])\n            deltas = [(-1, 0), (0, 1), (1, 0), (0, -1)]\n            result = []\n            for delta in deltas:\n                new_cell = (cell[0]+delta[0], cell[1]+delta[1])\n                if 0 <= new_cell[0] < M and 0 <= new_cell[1] < N:\n                    result.append(new_cell)\n            return result\n        \n        q = [(((0, 0), k), 0)]\n        M = len(grid)\n        N = len(grid[0])\n        \n        visited = set()\n        while q:\n            state, step_cnt = q.pop(0)\n            if state in visited:\n                continue\n            \n            visited.add(state)\n            cell, remaining_power = state\n            if cell[0] == M-1 and cell[1] == N-1:\n                return step_cnt\n            \n            if grid[cell[0]][cell[1]] == 1:\n                if remaining_power <= 0:\n                    continue\n                else:\n                    remaining_power -= 1\n            \n            for neigh in get_neighs(cell, grid):\n                if (neigh, remaining_power) not in visited:\n                    q.append(((neigh, remaining_power), step_cnt+1))\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        m, n = len(grid), len(grid[0])\n        def get_neighbors(i, j):\n            neighbors = [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]\n            return [(x, y) for x, y in neighbors if x >= 0 and x <= m-1 and y >= 0 and y <= n-1]\n                    \n                    \n        visited = set()\n        frontier = deque([(0, 0, 0)])\n        level = 0\n        while len(frontier) > 0:\n            for i in range(len(frontier)):\n                x, y, obs = frontier.popleft()\n                \n                if x == m-1 and y == n-1:\n                    return level\n                \n                if (x, y, obs) not in visited:\n                    neighbors = get_neighbors(x, y)\n                    if grid[x][y] == 1:\n                        if obs == k:\n                            continue\n                        else:\n                            frontier.extend([(x, y, obs+1) for x, y in neighbors])\n                    else:\n                        frontier.extend([(x, y, obs) for x, y in neighbors])\n                    visited.add((x, y, obs))\n            level += 1\n            \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        R, C = len(grid), len(grid[0])\n        q = [(0, 0, 0, k)]\n        seen = {}\n        while len(q) > 0:\n            i, j, steps, quota = q.pop(0)\n            if i < 0 or i == R or j < 0 or j == C:\n                continue\n            \n            if grid[i][j] == 1:\n                quota -= 1\n            \n            if quota == -1:\n                continue\n            \n            if i+1 == R and j+1 == C:\n                return steps\n            \n            key = (i, j, quota)\n            if key in seen:\n                continue\n            seen[key] = steps\n            \n            q.append((i-1, j, steps+1, quota))\n            q.append((i+1, j, steps+1, quota))\n            q.append((i, j-1, steps+1, quota))\n            q.append((i, j+1, steps+1, quota))\n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        '''\n            node, depth, k\n        '''\n        \n        \n        R,C = len(grid), len(grid[0])\n        \n        def neighbors(r, c):\n            for nr, nc in ((r-1,c),(r,c-1),(r+1,c),(r,c+1)):\n                if 0 <= nr < R and 0 <= nc < C:\n                    yield nr, nc            \n                    \n        target = (R-1,C-1)\n        q = deque([((0,0), 0, k)])\n        \n        seen = set()\n        \n        while q:\n            node, depth, k = q.popleft()\n            if (node,k) not in seen:\n                seen.add((node, k))\n\n                if node==target:\n                    return depth\n\n                for r,c in neighbors(*node):\n                    if grid[r][c]==1 and k>0:\n                        q.append(((r,c),depth+1, k-1))\n                    elif grid[r][c]==0:\n                        q.append(((r,c),depth+1, k))\n            \n        return -1                             ", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        x_a = [1, 0, -1, 0]\n        y_a = [0, -1, 0, 1]\n        \n        visited = {\\\"0 0 0\\\"}\n        nbours = [(0,0,0)]\n        steps = 0\n        while nbours:            \n            new_nbours = []\n            for coord in nbours:\n                if coord[0] == len(grid[0]) - 1 and coord[1] == len(grid) - 1:\n                    return steps\n                for x, y in zip(x_a, y_a):\n                    new_x = coord[0] + x\n                    new_y = coord[1] + y\n                    if 0 <= new_x < len(grid[0]) and 0 <= new_y < len(grid):\n                        new_k = coord[2] + 1\n                        if grid[new_y][new_x] == 1:\n                            if new_k <= k:\n                                new_coord = (new_x, new_y, new_k)\n                            else:\n                                continue\n                        else:\n                            new_coord = (new_x, new_y, coord[2])\n                        s = str(new_coord[0]) + \\\" \\\" + str(new_coord[1]) + \\\" \\\" +  str(new_coord[2])\n                        if s not in visited:\n                            new_nbours.append(new_coord)\n                            visited.add(s)\n            steps += 1\n            nbours = new_nbours\n        return -1\n            \n            \n                    ", "from collections import deque\ndef bfs(a, k):\n    dirs = [[0,1], [0,-1], [1,0], [-1,0]]\n    if a[0][0] == 1 and k==0:\n        return -1\n    q = deque()\n    q.append(((0,0),k-a[0][0], 0))\n    visited = set()\n    while q:\n        item, k, dist = q.popleft()\n        if (item, k) in visited:\n            continue\n        if item == (len(a)-1, len(a[0])-1):\n            return dist\n        visited.add((item, k))\n        for dir in dirs:\n            x = item[0] +dir[0]\n            y = item[1] +dir[1]\n            if 0<=x<len(a) and 0<=y<len(a[0]):\n                if a[x][y] == 0:\n                    q.append(((x,y),k, dist +1))\n                else:\n                    if k>0:\n                        q.append(((x,y),k-1, dist +1))\n    return -1\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        return bfs(grid, k)", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        queue = collections.deque([(0, 0, k, 0)])\n        visited = set()\n        # visited.add((0, 0, k))\n        dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)]\n        \n        if m == 1 and n == 1:\n            return 0\n        \n        while queue:\n            row, col, elim, steps = queue.popleft()\n            for x, y in dirs:\n                new_row, new_col = row + x, col + y\n                if 0 <= new_row < m and 0 <= new_col < n:\n                    if grid[new_row][new_col] == 1 and elim > 0 and (new_row, new_col, elim + 1) not in visited:\n                        queue.append((new_row, new_col, elim - 1, steps + 1))\n                        visited.add((new_row, new_col, elim - 1))\n                    if grid[new_row][new_col] == 0 and (new_row, new_col, elim) not in visited:\n                        if new_row == m - 1 and new_col == n - 1:\n                            return steps + 1\n                        else:\n                            queue.append((new_row, new_col, elim, steps + 1))\n                            visited.add((new_row, new_col, elim))\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or len(grid) == 0 or len(grid[0]) == 0:\n            return -1\n        queue = deque([])\n        m, n = len(grid), len(grid[0])\n        start_point = (0, 0, 0) if grid[0][0] != 1 else (0, 0, 1)\n        queue.append(start_point)\n        step = 0\n        seen = [[float(\\\"inf\\\")] * n for _ in range(m)]\n        \n        while len(queue) > 0:\n            count = len(queue)\n            for _ in range(count):\n                x, y, obs = queue.popleft()\n                if x == m - 1 and y == n - 1:\n                    return step\n\n                for next_x, next_y in [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]]:\n                    if 0 <= next_x < m and 0 <= next_y < n:\n                        num_obs = obs + grid[next_x][next_y]\n                        if num_obs >= seen[next_x][next_y] or num_obs > k:\n                            continue\n                        seen[next_x][next_y] = num_obs\n                        queue.append((next_x, next_y, num_obs))\n            step += 1\n\n        return -1\n        \n        ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:        \n        if not len(grid) or not len(grid[0]):\n            return -1\n        \n        seen = set()\n        m = len(grid)\n        n = len(grid[0])\n        \n        def validMove(x, y):\n            return x >= 0 and y >= 0 and x < m and y < n and (x,y) not in seen\n        \n        q = [(0, 0, 0, 0)]\n        \n        while q:\n            x, y, z, obs = q.pop(0)\n            if x == m-1 and y == n-1:\n                return z\n                \n            if (x, y, obs) in seen:\n                continue\n                \n            seen.add((x, y, obs))\n            if grid[x][y] == 1 and obs == k:\n                continue\n            obs += grid[x][y] == 1\n                \n            dirs = [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]\n            \n            for d in dirs:\n                if validMove(*d):\n                    a, b = d\n                    q.append((d[0], d[1], z+1, obs))\n        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        R, C = len(grid), len(grid[0])\n        heap = [(0, k, 0, 0)] # length, elimination, i, j\n        visited = set()\n        \n        while heap:\n            l, e, i, j = heapq.heappop(heap)\n            if i == R - 1 and j == C - 1:\n                return l\n            if e < 0:\n                continue\n            if (i, j, e) in visited:\n                continue\n            visited.add((i, j, e))\n            for x, y in [(i+1, j), (i, j+1), (i-1, j), (i, j-1)]:\n                if x < 0 or x >= R or y < 0 or y >= C:\n                    continue\n                heapq.heappush(heap, (l+1, e - grid[x][y], x, y))\n                \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rows, cols = len(grid), len(grid[0])\n        if rows == 1 and cols == 1:\n            return 0\n\n        visited = set((0, 0, k))\n        q = deque([(0, 0, k, 0)])\n        while q:\n            r, c, k_rem, d = q.popleft()\n            edges = [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]\n            edges = [(x, y) for x, y in edges if x >= 0 and x < rows and y >= 0 and y < cols]\n            edges = [(x, y, (k_rem - 1) if grid[x][y] == 1 else k_rem) for x, y in edges]\n            edges = [edge for edge in edges if edge[2] >= 0 and edge not in visited]\n            for x, y, rem in edges:\n                if x == rows - 1 and y == cols - 1:\n                    return d + 1\n                q.append((x, y, rem, d + 1))\n                visited.add((x, y, rem))\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        \n        import queue\n        queue = queue.Queue()\n        queue.put((0, 0, k))\n        visited = set([(0, 0, k)])\n        \n        steps = 0\n        while not queue.empty():\n            size = queue.qsize()\n            for _ in range(size):\n                x, y, c = queue.get()\n                # print(x, y)\n                if x == m - 1 and y == n - 1:\n                    return steps\n                for delta_x, delta_y in [(0, 1), (0, -1), (1, 0), (-1, 0)]:\n                    x_, y_ = x + delta_x, y + delta_y\n                    # print(x_, y_)\n                    if x_ < 0 or x_ >= m or y_ < 0 or y_ >= n:\n                        continue\n                    if grid[x_][y_] == 1 and c > 0 and (x_, y_, c - 1) not in visited:\n                        queue.put((x_, y_, c - 1))\n                        visited.add((x_, y_, c - 1))\n                    if grid[x_][y_] == 0 and (x_, y_, c) not in visited:\n                        queue.put((x_, y_, c))\n                        visited.add((x_, y_, c))\n            steps += 1\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        job_list = deque()\n        def def_value():\n            return []\n        graph = defaultdict(def_value)\n        dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]\n        def inBounds(i, j):\n            return 0 <= i and i < m and 0 <= j and j < n\n        \n        for i in range(m):\n            for j in range(n):\n                for dir_pair in dirs:\n                    next_point_i = i + dir_pair[0]\n                    next_point_j = j + dir_pair[1]\n                    if inBounds(next_point_i, next_point_j):\n                        if grid[next_point_i][next_point_j] == 1:\n                            graph[(i, j)].append((next_point_i, next_point_j, 1))\n                        else:\n                            graph[(i, j)].append((next_point_i, next_point_j, 0))\n        \n        job_list.append((0, 0, k, 0))\n        visited_set = set()\n        #print(graph)\n        while len(job_list) > 0:\n            cur = job_list.popleft()\n            if cur[0] == m-1 and cur[1] == n-1:\n                return cur[3]\n            if (cur[0], cur[1], cur[2]) not in visited_set:\n                visited_set.add((cur[0], cur[1], cur[2]))\n            else:\n                continue\n            \n            neighbors = graph[(cur[0], cur[1])]\n            for neighbor in neighbors:\n                if neighbor[2] == 1:\n                    if cur[2] > 0:\n                        job_list.append((neighbor[0], neighbor[1], cur[2]-1, cur[3] + 1))\n                else:\n                    job_list.append((neighbor[0], neighbor[1], cur[2], cur[3] + 1))\n        if (m-1, n-1) not in visited_set:\n            return -1\n        else:\n            return visited_set[(m-1, n-1)]\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        R, C = len(grid), len(grid[0])\n        if R == C == 1: return 0\n        \n        visited = [[[float('inf') for _ in range(C)] for _ in range(R)] for _ in range(k+1)]\n        \n        #visited[breaks remaining][row][column]\n        \n        q = [(0, k, 0, 0)]\n        best = float('inf')\n        \n        while q:\n            \n            steps, b, r, c = heapq.heappop(q)\n            \n            if (b < 0) or (steps >= best):\n                continue\n            \n            if steps >= visited[b][r][c]:\n                continue\n            if (r == R-1) and (c == C-1):\n                best = min(best, steps)\n            visited[b][r][c] = steps\n            \n            for i,j in ((r+1,c),(r,c+1),(r-1,c),(r,c-1)):\n                if (0 <= i < R) and (0 <= j < C) and (visited[b - grid[i][j]][i][j] > steps + 1):\n                    heapq.heappush(q, (steps + 1, b - grid[i][j], i, j))\n        \n        res = min((visited[b][R-1][C-1] for b in range(k+1)))\n        return res if (res != float('inf')) else -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        M = len(grid)\n        N = len(grid[0])\n        visited = set()\n        q = deque([(0, 0, k, 0)])\n        while q:\n            data = q.popleft()\n            #print(data)\n            x, y = data[0], data[1]\n            k = data[2]\n            if (x, y, k) not in visited:\n                visited.add((x, y, k))\n                if x == M-1 and y == N-1:\n                    return data[3]\n\n                k = data[2]\n                steps = data[3]\n\n                for i, j in [(-1, 0), (1, 0), (0, 1), (0, -1)]:\n                    if  0 <= x+i < M and  0 <= y+j < N:\n                        if grid[x+i][y+j] == 1:\n                            if k >= 1:\n                                q.append((x+i, y+j, k-1, steps+1))\n                        else:\n                            q.append((x+i, y+j, k, steps+1))\n        \n        return -1\n                        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # lets dp it\n        # one way is to get all the paths using the obs\n        heap = []\n        heapq.heappush(heap,(0,0,0,k))\n        \n        m = len(grid)\n        n = len(grid[0])\n        visited = set()\n        while heap:\n            cost,i,j,k = heapq.heappop(heap)\n            \n            if (i,j)==(m-1,n-1):\n                return(cost)\n            \n            if (i,j,k) in visited:\n                continue\n                \n            visited.add((i,j,k))\n            \n            for x,y in [(0,1),(1,0),(0,-1),(-1,0)]:\n                x_new = x + i\n                y_new = y + j\n                \n                if 0<=x_new<m and 0<=y_new<n:\n                    if grid[x_new][y_new] == 0:\n                        heapq.heappush(heap,(cost+1,x_new,y_new,k))\n                    elif grid[x_new][y_new] and k:\n                        heapq.heappush(heap,(cost+1,x_new,y_new,k-1))\n        return -1\n", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        self.g = grid\n        visited = set()\n        visited.add((0,0,0))\n        \n        q = collections.deque()\n        q.append((0,0,0,0))\n        \n        target = (len(grid)-1, len(grid[0])-1)\n        \n        while q:\n            node = q.popleft()\n            \n            if (node[0], node[1]) == target:\n                return node[3]\n            \n            for n in self.neigh(node):\n                nk = node[2] + (1 if grid[n[0]][n[1]] == 1 else 0)\n                if (n[0], n[1], nk) not in visited and nk <= k:\n                    visited.add((n[0], n[1], nk))\n                    q.append((n[0], n[1], nk, node[3]+1))\n        \n        return -1\n                \n        \n        \n    def neigh(self, pos):\n        cand = [\n            (pos[0]+1, pos[1]),\n            (pos[0]-1, pos[1]),\n            (pos[0], pos[1]+1),\n            (pos[0], pos[1]-1)\n        ]\n        \n        out = []\n        \n        for c in cand:\n            if c[0] >= 0  and c[0] < len(self.g) and c[1] >= 0 and c[1] < len(self.g[0]):\n                out.append(c)\n        \n        return out\n    \n    \n", "class Solution(object):\n    def shortestPath(self, grid, k):\n        k -= grid[0][0] == 1\n        if k < 0: return -1\n        n, m = len(grid), len(grid[0])\n        if k >= m + n - 3:\n            return m + n - 2\n        n, m = n-1, m-1\n        bfs = [(0, 0, k)] # i, j, remaining removals\n        seen = set()\n        steps = 0\n        while bfs:\n            nxt = []\n            for i, j, rem in bfs:\n                if(i, j, rem) in seen: continue\n                if i == n and j == m: return steps\n                if i > 0:\n                    nrem = rem - (grid[i-1][j] == 1)\n                    if nrem >= 0: \n                        nxt.append((i-1, j, nrem))\n                if j > 0:\n                    nrem = rem - (grid[i][j-1] == 1)\n                    if nrem >= 0: \n                        nxt.append((i, j-1, nrem))\n                if i < n:\n                    nrem = rem - (grid[i+1][j] == 1)\n                    if nrem >= 0: \n                        nxt.append((i+1, j, nrem))\n                if j < m:\n                    nrem = rem - (grid[i][j+1] == 1)\n                    if nrem >= 0: \n                        nxt.append((i, j+1, nrem))\n                seen.add((i, j, rem))\n            steps += 1\n            bfs = nxt\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def dfs(x, y, delete, used, dp):\n            if x==len(grid)-1 and y==len(grid[0])-1:\n                return 0\n            if (x, y, delete) in dp:\n                return dp[(x,y,delete)]\n            result = float('inf')\n            \n            if 0<=x<len(grid) and 0<=y<len(grid[0]):\n                if grid[x][y]==1:\n                    if delete==0:\n                        dp[(x,y,delete)] = float('inf')\n                        return float('inf')\n                    delete -= 1\n                \n                used.add((x,y))\n                for dx, dy in step:\n                    tx = x+dx\n                    ty = y+dy\n                    if (tx, ty) not in used:\n                        result = min(result, dfs(tx, ty, delete, used, dp)+1)\n                used.remove((x,y))\n                dp[(x,y,delete)] = result\n            return result\n                    \n        shortest = len(grid)+len(grid[0])-2\n        if k >= shortest:\n            return shortest\n        step = [[1, 0], [0, 1], [0, -1], [-1, 0]]\n        res = dfs(0, 0, k, set(), {})\n        return res if res != float('inf') else -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = [[0,0,0,k]]\n        row, col = len(grid), len(grid[0])\n        visit = set()\n        while queue:\n            step, x, y, ob = heapq.heappop(queue)\n            if x == row-1 and y == col-1:\n                return step\n            if (x, y, ob) not in visit:\n                visit.add((x, y, ob))\n                for m, n in [[x+1,y],[x-1,y],[x,y+1],[x,y-1]]:\n                    if 0<=m<row and 0<=n<col:\n                        if not grid[x][y]:\n                            heapq.heappush(queue, [step+1, m, n, ob])\n                        elif ob:\n                            heapq.heappush(queue, [step+1, m, n, ob-1])\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = []\n        visited = set()\n        q.append([0, 0, k - grid[0][0], 0])\n        visited.add((0, 0, k - grid[0][0]))\n        step = [[1, 0], [-1, 0], [0, 1], [0, -1]]\n        n = len(grid)\n        m = len(grid[0])\n        \n        if (n == 1) and (m == 1) and (q[0][2] >= 0):\n            return 0\n        \n        while (q):\n            now = q.pop(0)\n            # print(now)\n            # print(visited)\n            for i in range(4):\n                new = [ now[0] + step[i][0], now[1] + step[i][1], 0, now[3] + 1]\n                if (0 <= new[0] < n) and (0 <= new[1] < m):\n                    i = new[0]\n                    j = new[1]\n                    new[2] = now[2] - grid[i][j]\n                    # if (i == n - 1) and (j == m - 1):\n                    #     print(new)\n                    #     print(visited)\n                    if (new[2] >= 0) and ((tuple(new[:3])) not in visited):\n                        if (i == n - 1) and (j == m - 1):\n                            return new[3]\n                        q.append(new)\n                        visited.add(tuple(new[:3]))\n        return -1\n                        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        m, n = len(grid), len(grid[0])\n        cnt = 0\n        self.stones = [[0]*n for _ in range(m)]\n        cols = [[0]*n for _ in range(m)]\n        for i in range(m-1,-1,-1):\n            for j in range(n-1,-1,-1):\n                if i==m-1 and j==n-1:\n                    self.stones[i][j] = grid[i][j]\n                    cols[i][j] = grid[i][j]\n                elif j==n-1:\n                    self.stones[i][j] = grid[i][j] + self.stones[i+1][j]\n                    cols[i][j] = grid[i][j] + cols[i+1][j]\n                elif i==m-1:\n                    self.stones[i][j] = grid[i][j] + self.stones[i][j+1]\n                    cols[i][j] = grid[i][j]\n                else:\n                    self.stones[i][j] = grid[i][j] + self.stones[i][j+1] + cols[i+1][j]\n                    cols[i][j] = grid[i][j] + cols[i+1][j]\n                        \n            \n        self.memo = {}\n        \n        path = self.dfs(grid, 0, 0, k, set([(0,0,k)]))\n        if path == sys.maxsize:\n            return -1\n        return path\n        \n    def dfs(self, grid, x, y, k, visited):\n        \n        m, n = len(grid), len(grid[0])\n        if self.stones[x][y] <= k:\n            self.memo[x,y,k] = (m-1-x)+(n-1-y)\n            return self.memo[x,y,k]\n        \n        if grid[x][y] == 1: k -= 1\n           \n        if k < 0: return sys.maxsize\n        if x == m-1 and y==n-1: return 0\n        if (x,y,k) in self.memo: return self.memo[x,y,k] \n        \n        directions = [[1,0],[0,1],[-1,0],[0,-1]]\n        shortest = sys.maxsize\n        for dx, dy in directions:\n            nx, ny = dx+x, dy+y\n            if nx<0 or ny<0 or nx>=m or ny>=n or (nx,ny,k) in visited:\n                continue\n                \n            visited.add((nx, ny, k))\n            shortest = min(shortest, self.dfs(grid, nx, ny, k, visited)+1)\n            visited.remove((nx, ny, k))\n           \n         \n        self.memo[x,y,k] = shortest\n        \n        return shortest\n            \n        \n        \n        \n", "import heapq\nfrom collections import deque\nfrom typing import List, Dict, Tuple\n\nclass Solution:\n\n    def getNeighbors(self, grid: List[List[int]], ycor: int, xcor: int) -> List[List[int]]:\n\n        directions = [\n            (-1, 0),\n            (1,  0),\n            (0,  1),\n            (0, -1)\n        ]\n\n        neighbors = []\n\n        for delta_y, delta_x in directions:\n\n            new_y = ycor + delta_y\n            new_x = xcor + delta_x\n\n            if new_y > -1 and new_y < len(grid) and \\\\\n               new_x > -1 and new_x < len(grid[0]):\n\n                neighbors.append( (new_y, new_x) )\n\n        return neighbors\n\n\n    def v0(self, grid: List[List[int]], k: int) -> int:\n\n        # Start at 0,0, with 0 distance traveled, and 0 blocks destroyed.\n        queue = deque([ (0, 0, 0, 0) ])\n\n        # Keep a visited set so we don't end up in a cycle.\n        visited = set([])\n\n        while queue:\n\n            ycor, xcor, num_steps, destroyed = queue.popleft()\n\n            if ycor == len(grid) - 1 and xcor == len(grid[0]) - 1:\n                return num_steps\n\n            # Adding to visited after we enter it, makes this solution more\n            # symmetric to the Djikstra type questions.\n            elif (ycor, xcor) not in visited:\n\n                visited.add( (ycor, xcor) )\n\n                for neighbor_y, neighbor_x in self.getNeighbors(grid, ycor, xcor):\n\n                    if grid[neighbor_y][neighbor_x] in (0, '0'):\n                        queue.append( (neighbor_y, neighbor_x, num_steps + 1, destroyed) )\n                    elif destroyed < k:\n                        queue.append( (neighbor_y, neighbor_x, num_steps + 1, destroyed + 1) )\n\n        return -1\n\n\n    def v1(self, grid: List[List[int]], k: int) -> int:\n        \\\"\\\"\\\"\n        Welp, somewhere deep in the test cases, my original solution breaks,\n        presumably due to my \\\"visited\\\" strategy closing off a path that\n        includes destroying a block even though it's shorter.\n        \\\"\\\"\\\"\n        # Start at 0,0, with 0 distance traveled, and 0 blocks destroyed.\n        queue = [ (0, 0, 0, 0) ]\n\n        # Keep a visited set so we don't end up in a cycle.\n        visited = set([])\n\n        while queue:\n\n            num_steps, ycor, xcor, destroyed = heapq.heappop(queue)\n\n            if ycor == len(grid) - 1 and xcor == len(grid[0]) - 1:\n                return num_steps\n\n            # Adding to visited after we enter it, makes this solution more\n            # symmetric to the Djikstra type questions.\n            elif (ycor, xcor, destroyed) not in visited:\n\n                visited.add( (ycor, xcor, destroyed) )\n\n                for neighbor_y, neighbor_x in self.getNeighbors(grid, ycor, xcor):\n\n                    if grid[neighbor_y][neighbor_x] in (0, '0'):\n                        heapq.heappush( queue, ( num_steps + 1, neighbor_y, neighbor_x, destroyed) )\n                    elif destroyed < k:\n                        heapq.heappush( queue, ( num_steps + 1, neighbor_y, neighbor_x, destroyed + 1) )\n\n        return -1\n\n\n    def dfs(self, grid: List[List[int]], ycor: int, xcor: int,\n            destroys_remaining: int, steps_taken: int, path: List[int]) -> int:\n        \\\"\\\"\\\"\n        The sub-worker function.\n        \\\"\\\"\\\"\n        if ycor == len(grid) - 1 and xcor == len(grid[0]) - 1:\n            return steps_taken\n\n        else:\n\n            sub_paths = []\n\n            min_sub_path = float('inf')\n            min_y = None\n            min_x = None\n\n            for neighbor_y, neighbor_x in self.getNeighbors(grid, ycor, xcor):\n\n                # We'll keep a local history of points visited in the current\n                # path, rather than a nonlocal \\\"visited\\\" set.\n                if (neighbor_y, neighbor_x) not in path:\n\n                    possible = float('inf')\n\n                    if grid[neighbor_y][neighbor_x] in (0, '0'):\n                        possible = self.dfs(grid, neighbor_y, neighbor_x,\n                                            destroys_remaining, steps_taken + 1,\n                                            path + [(neighbor_y, neighbor_x)])\n\n                    elif destroys_remaining > 0:\n                        possible = self.dfs(grid, neighbor_y, neighbor_x,\n                                            destroys_remaining - 1, steps_taken + 1,\n                                            path + [(neighbor_y, neighbor_x)])\n\n                    if possible < min_sub_path:\n                        min_sub_path = possible\n                        min_y = neighbor_y\n                        min_x = neighbor_x\n\n            return min_sub_path\n\n\n    def v2(self, grid: List[List[int]], k: int) -> int:\n        \\\"\\\"\\\"\n        Nope, I suck. By using a visited set, I am now closing off paths that\n        move BACKWARDS, but are valid. I guess I really do need to use a DFS\n        after all.\n\n        UPDATE: Nevermind, DFS runs into \\\"time limit exceeded.\\\" What I really\n        should have done is also use \\\"destroyed\\\" as a key in the BFS\n        implementation. Going back to using that.\n        \\\"\\\"\\\"\n        min_steps = self.dfs(grid, 0, 0, k, 0, [])\n\n        if min_steps == float('inf'):\n            return -1\n        else:\n            return min_steps\n\n\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        #return self.v0(grid, k)\n        return self.v1(grid, k)\n        #return self.v2(grid, k)\n\n    def main(self):\n        assert(self.shortestPath([\n            [0,0,0],\n            [1,1,0],\n            [0,0,0],\n            [0,1,1],\n            [0,0,0],\n        ], 1) == 6)\n\n        assert(self.shortestPath([\n            [0,1,1],\n            [1,1,1],\n            [1,0,0],\n        ], 1) == -1)\n\n        assert(self.shortestPath([\n            [0,0],\n            [1,0],\n            [1,0],\n            [1,0],\n            [1,0],\n            [1,0],\n            [0,0],\n            [0,1],\n            [0,1],\n            [0,1],\n            [0,0],\n            [1,0],\n            [1,0],\n            [0,0]\n        ], 4) == 14)\n\n        assert(self.shortestPath([\n            [0,1,0,0,0,1,0,0],\n            [0,1,0,1,0,1,0,1],\n            [0,0,0,1,0,0,1,0]\n        ], 1) == 13)\n", "import queue\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = queue.Queue()\n        \n        q.put([0, 0, k, 0]) # row, col, k, level\n        visited = set()\n        dir_ = [[0, 1], [0, -1], [-1, 0], [1, 0]]\n        visited.add((0, 0, k))\n        while not q.empty():\n            r, c, cur_k, level = q.get()\n            if r == len(grid) - 1 and c == len(grid[0]) -1:\n                return level\n            for x, y in dir_:\n                nr, nc = x + r, y + c\n                if not (0 <= nr < len(grid) and 0 <= nc < len(grid[0])) :\n                    continue \n                    \n                if grid[nr][nc] == 1 and cur_k > 0 and (nr, nc, cur_k-1) not in visited:\n                    q.put([nr, nc, cur_k-1, level+1])\n                    visited.add((nr, nc, cur_k-1))\n                if grid[nr][nc] == 0 and (nr, nc, cur_k) not in visited:\n                    q.put([nr, nc, cur_k, level+1])\n                    visited.add((nr, nc, cur_k))\n                if nr == len(grid) - 1 and nc == len(grid[0]) - 1:\n                    return level + 1\n        return -1 ", "import queue\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        if m == n and n == 1:\n            return 0\n        dirs = [(0,1), (1,0), (0,-1), (-1,0)]\n        q = queue.Queue()\n        q.put(((0,0), 0, k))\n        vis = set()\n        vis.add((0,0,k))\n        while not q.empty():\n            (x,y), dist, rem = q.get()\n            for d in dirs:\n                nx, ny = x+d[0], y+d[1]\n                if 0 <= nx < m and 0 <= ny < n:\n                    if (nx, ny, rem) in vis:\n                        continue\n                    if (nx, ny) == (m-1, n-1):\n                        return dist+1\n                    if grid[nx][ny] == 0:\n                        q.put(((nx, ny), dist+1, rem))\n                    elif rem > 0:\n                        q.put(((nx, ny), dist+1, rem - 1))\n                    vis.add((nx, ny, rem))\n        return -1\n\n    def shortestPath1(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        dirs = [(0,1), (1,0), (0,-1), (-1,0)]\n        q = queue.Queue()\n        q.put(((0,0), 0))\n        while not q.empty():\n            (x,y), dist = q.get()\n            for d in dirs:\n                nx, ny = x+d[0], y+d[1]\n                if 0 <= nx < m and 0 <= ny < n:\n                    if (nx, ny) == (m-1, n-1):\n                        return dist+1\n                    if grid[nx][ny] == 0:\n                        q.put(((nx, ny), dist+1))\n        return -1\n\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        dst = (len(grid)-1, len(grid[0])-1)\n        heap = [(0, 0, (0, 0))] #cost, stop, node\n        cost_map = collections.defaultdict(lambda: float('inf'))\n        while heap:\n            cost, stop, node = heapq.heappop(heap)\n            if stop > k or cost>=cost_map[(stop, node)]:\n                continue\n            if node == dst:\n                return cost\n            cost_map[(stop, node)] = cost\n            i, j = node\n            for n_i, n_j in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]:\n                if n_i < 0 or n_j < 0 or n_i >= m or n_j >= n:\n                    continue\n                if (n_i, n_j) == dst:\n                    return cost+1\n                if grid[n_i][n_j] == 0:\n                    heapq.heappush(heap, (cost+1, stop, (n_i, n_j)))\n                else:\n                    if stop+1<=k:\n                        heapq.heappush(heap, (cost+1, stop+1, (n_i, n_j)))\n                \n        return -1", "from queue import Queue\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n = len(grid)\n        m = len(grid[0])\n        q = Queue()\n        if k == 0 and grid[0][0] == 1:\n            return -1\n        shortest_path = dict()\n        def get_neighbors(r, c):\n            neighbors = []\n            for ri, ci in [(r-1, c), (r, c-1), (r+1, c), (r, c+1)]:\n                if ri < 0 or ci < 0 or ri == n or ci == m:\n                    continue\n                neighbors.append((ri, ci))\n            return neighbors\n        \n        q.put((0,0,grid[0][0]))\n        shortest_path[(0,0,grid[0][0])]=0\n        while q.qsize() > 0:\n            r, c, d = q.get()\n            if r == n-1 and c == m-1:\n                return shortest_path[(r,c,d)]\n            neighbors = get_neighbors(r,c)\n            for ri, ci in neighbors:\n                if d+grid[r][c] > k or (ri, ci, d+grid[r][c]) in shortest_path:\n                    continue\n                q.put((ri, ci, d+grid[r][c]))\n                shortest_path[(ri, ci, d+grid[r][c])] = shortest_path[(r,c,d)] + 1\n        return -1                ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        queue = collections.deque([(0, 0, k, 0)])\n        visited = set()\n        visited.add((0, 0, k))\n        dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)]\n        \n        if m == 1 and n == 1:\n            return 0\n        \n        while queue:\n            row, col, remain, steps = queue.popleft()\n            for x, y in dirs:\n                new_row, new_col = row + x, col + y\n                if 0 <= new_row < m and 0 <= new_col < n:\n                    if remain > 0 and grid[new_row][new_col] == 1 and (new_row, new_col, remain + 1) not in visited:\n                        queue.append((new_row, new_col, remain - 1, steps + 1))\n                        visited.add((new_row, new_col, remain - 1))\n                    if grid[new_row][new_col] == 0 and (new_row, new_col, remain) not in visited:\n                        if new_row == m - 1 and new_col == n - 1:\n                            return steps + 1\n                        else:\n                            queue.append((new_row, new_col, remain, steps + 1))\n                            visited.add((new_row, new_col, remain))\n                            \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q, nq, d, vis = {(0,0)}, set(), {(0,0):(0,0)}, set()\n        # import numpy as np\n        # A = np.zeros((len(grid),len(grid[0])))\n        # for i,j in itertools.product(range(len(grid)),range(len(grid[0]))):\n        #     A[i,j] = grid[i][j]\n        while q:\n            vis = set.union(vis,q)\n            for i,j in q:\n                # print(\\\"\\\nparent node:\\\",i,j)\n                for m,n in [(i-1,j),(i,j-1),(i+1,j),(i,j+1)]:\n                    in_grid = 0<=m<len(grid) and 0<=n<len(grid[0])\n                    dist, obst = d[(i,j)]\n                    if in_grid:\n                        obst += 1 if grid[m][n]==1 else 0\n                        if obst < d.get((m,n),(0,float('inf')))[1]:\n                            d[(m,n)] = (dist+1,obst)\n                            nq.add((m,n))\n                    x, y = d.get((len(grid)-1, len(grid[0])-1),(0,float('inf')))\n                    if y <= k:\n                        return x\n            q, nq = nq, set()\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        \n        min_d = [[math.inf for i in range(n)] for j in range(m)]\n        min_d[0][0] = 0\n        todo = collections.deque()\n        todo.append((0, 0, 0))\n        def adjust():\n            while todo:\n                x, y, d = todo.popleft()\n                for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                    nx, ny = x + dx, y + dy\n                    if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 0 and min_d[nx][ny] > d + 1:\n                        min_d[nx][ny] = d + 1\n                        todo.append((nx, ny, d + 1))\n        adjust()\n        \n        blockes = []\n        for x in range(m):\n            for y in range(n):\n                if grid[x][y] == 1:\n                    blockes.append((x, y))\n        min_d_to_block = {}\n        \n        for i in range(k):\n            delay_update = []\n            for x, y in blockes:\n                d = math.inf\n                for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                    nx, ny = x + dx, y + dy\n                    if 0 <= nx < m and 0 <= ny < n and min_d[nx][ny] != math.inf:\n                        d = min(d, min_d[nx][ny] + 1)\n                if min_d[x][y] > d:\n                    delay_update.append((x, y, d))\n                    todo.append((x, y, d))\n            for x, y, d in delay_update:\n                min_d[x][y] = d\n            adjust()\n            \n        print(min_d)\n        return -1 if min_d[m-1][n-1] == inf else min_d[m-1][n-1]", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        heap = [[0,-k,0,0]]\n        seen = set()\n        while heap:\n            step, block, i, j = heappop(heap)\n            \n            if (i,j,block) in seen:\n                continue\n            seen.add((i,j,block))\n            \n            if (i,j) == (m-1,n-1):\n                return step\n            \n            for ni,nj in [[i+1,j], [i-1,j], [i,j+1], [i,j-1]]:\n                if 0 <= ni < m and 0 <= nj < n:\n                    if grid[ni][nj] == 0:\n                        if (ni,nj,block) not in seen:\n                            heappush(heap, [step+1, block, ni, nj])\n                    elif block + 1 <= 0 and (ni,nj,block+1) not in seen:\n                        heappush(heap, [step+1, block+1, ni, nj])\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        \n        min_d = [[math.inf for i in range(n)] for j in range(m)]\n        min_d[0][0] = 0\n        todo = collections.deque()\n        todo.append((0, 0, 0))\n        def adjust():\n            while todo:\n                x, y, d = todo.popleft()\n                for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                    nx, ny = x + dx, y + dy\n                    if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 0 and min_d[nx][ny] > d + 1:\n                        min_d[nx][ny] = d + 1\n                        todo.append((nx, ny, d + 1))\n        adjust()\n        \n        blockes = []\n        for x in range(m):\n            for y in range(n):\n                if grid[x][y] == 1:\n                    blockes.append((x, y))\n        min_d_to_block = {}\n        \n        for i in range(k):\n            delay_update = []\n            for x, y in blockes:\n                d = math.inf\n                for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                    nx, ny = x + dx, y + dy\n                    if 0 <= nx < m and 0 <= ny < n and min_d[nx][ny] != math.inf:\n                        d = min(d, min_d[nx][ny] + 1)\n                if min_d[x][y] > d:\n                    delay_update.append((x, y, d))\n                    todo.append((x, y, d))\n            for x, y, d in delay_update:\n                min_d[x][y] = d\n            adjust()\n            \n        return -1 if min_d[m-1][n-1] == inf else min_d[m-1][n-1]", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        \n        min_d = [[math.inf for i in range(n)] for j in range(m)]\n        min_d[0][0] = 0\n        todo = collections.deque()\n        todo.append((0, 0, 0))\n        def adjust():\n            while todo:\n                x, y, d = todo.popleft()\n                for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                    nx, ny = x + dx, y + dy\n                    if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 0 and min_d[nx][ny] > d + 1:\n                        min_d[nx][ny] = d + 1\n                        todo.append((nx, ny, d + 1))\n        adjust()\n        \n        blockes = []\n        for x in range(m):\n            for y in range(n):\n                if grid[x][y] == 1:\n                    blockes.append((x, y))\n        min_d_to_block = {}\n        \n        for i in range(k):\n            delay_update = []\n            for x, y in blockes:\n                d = math.inf\n                for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                    nx, ny = x + dx, y + dy\n                    if 0 <= nx < m and 0 <= ny < n and min_d[nx][ny] != math.inf:\n                        d = min(d, min_d[nx][ny] + 1)\n                if min_d[x][y] > d:\n                    delay_update.append((x, y, d))\n                    todo.append((x, y, d))\n            for x, y, d in delay_update:\n                min_d[x][y] = d\n            delay_update = []\n            adjust()\n            \n        return -1 if min_d[m-1][n-1] == inf else min_d[m-1][n-1]", "from heapq import *\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        def is_valid(i, j):\n            return 0 <= i < m and 0 <= j < n\n            \n        directions = [(1,0),(-1,0),(0,1),(0,-1)]\n        bfs = []\n        visited = set()\n        heappush(bfs, [0, k, (0, 0)])  # cur_moves, k, position\n        while bfs:\n            cur_moves, k_left, pos = heappop(bfs)\n            i, j = pos\n            # if cur_moves >=20:\n            #     print(cur_moves, k_left, pos)\n            if (i,j,k_left) in visited: continue\n            visited.add((i,j,k_left))\n            if pos == (m-1, n-1):\n                return cur_moves\n            \n            for di, dj in directions:\n                if not is_valid(i+di, j+dj): continue\n                if grid[i+di][j+dj] == 1 and k_left > 0:\n                    heappush(bfs, [cur_moves+1, k_left-1, (i+di, j+dj)])\n                elif grid[i+di][j+dj] == 0:\n                    heappush(bfs, [cur_moves+1, k_left, (i+di, j+dj)])\n                \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        steps = 0\n        directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        def checkValid(x, y):\n            return 0 <= x < m and 0 <= y < n\n        d = {}\n        @lru_cache(None)\n        def dp(i, j, p):\n            nonlocal steps\n            if p < 0:\n                return float('inf')\n            if i == m - 1 and j == n - 1:\n                return 0\n            d[(i, j, p)] = min(d.get((i, j, p), float('inf')), steps)\n            res = float('inf')\n            if steps >= m * n:\n                # print(steps)\n                return steps\n            for dr in directions:\n                x, y = i + dr[0], j + dr[1]\n                if x < 0 or x >= m or y < 0 or y >= n:\n                    continue\n                if grid[x][y] == 0:\n                    if steps + 1 <= d.get((x, y, p), float('inf')):\n                        steps += 1\n                        res = min(res, dp(x, y, p))\n                        steps -= 1\n                else:\n                    if steps + 1 <= d.get((x, y, p - 1), float('inf')):\n                        steps += 1\n                        grid[x][y] = 0\n                        res = min(res, dp(x, y, p - 1))\n                        grid[x][y] = 1\n                        steps -= 1\n            return res + 1\n        ans = float('inf')\n        # print(\\\"k = \\\", k)\n        ans = min(ans, dp(0, 0, k))\n        # for i in range(k, -1, -1):\n        #     ans = min(ans, dp(m - 1, n - 1, i))\n            # print(dp(m - 1, n - 1, i))\n        # print(dp(m - 1, n - 1, 283))\n        if ans > 10**10:\n            return -1\n        return ans\n            \n                    \n                \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        steps = 0\n        directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        def checkValid(x, y):\n            return 0 <= x < m and 0 <= y < n\n        d = {}\n        @lru_cache(None)\n        def dp(i, j, p):\n            nonlocal steps\n            if p < 0:\n                return float('inf')\n            if i == m - 1 and j == n - 1:\n                return 0\n            d[(i, j, p)] = min(d.get((i, j, p), float('inf')), steps)\n            res = float('inf')\n            if steps >= m * n:\n                return steps\n            for dr in directions:\n                x, y = i + dr[0], j + dr[1]\n                if x < 0 or x >= m or y < 0 or y >= n:\n                    continue\n                if grid[x][y] == 0:\n                    if steps + 1 <= d.get((x, y, p), float('inf')):\n                        steps += 1\n                        res = min(res, dp(x, y, p))\n                        steps -= 1\n                else:\n                    if steps + 1 <= d.get((x, y, p - 1), float('inf')):\n                        steps += 1\n                        grid[x][y] = 0\n                        res = min(res, dp(x, y, p - 1))\n                        grid[x][y] = 1\n                        steps -= 1\n            return res + 1\n        ans = dp(0, 0, k)\n        if ans > 10**10:\n            return -1\n        return ans\n            \n                    \n                \n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        heap = [[0,-k,0,0]]\n        seen = {}\n        while heap:\n            step, block, i, j = heappop(heap)\n            \n            if (i,j) in seen and seen[i,j] <= block:\n                continue\n            seen[i,j] = block\n            \n            if (i,j) == (m-1,n-1):\n                return step\n            \n            for ni,nj in [[i+1,j], [i-1,j], [i,j+1], [i,j-1]]:\n                if 0 <= ni < m and 0 <= nj < n:\n                    if grid[ni][nj] == 0:\n                        if (ni,nj) not in seen or seen[ni,nj] > block:\n                            heappush(heap, [step+1, block, ni, nj])\n                    elif block + 1 <= 0 and ((ni,nj) not in seen or seen[ni,nj] > block+1):\n                        heappush(heap, [step+1, block+1, ni, nj])\n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return -1\n        \n        if k >= len(grid) + len(grid[0]) - 2:\n            return len(grid) + len(grid[0]) - 2\n        \n        directions = ((0, 1), (0, -1), (-1, 0), (1, 0))\n        q = deque([(0, 0, k, 0)])\n        visited = set((0, 0, k))\n        while q:\n            r, c, obst_rem, steps = q.popleft()\n            for x, y in directions:\n                nxt_r, nxt_c = r + x, c + y\n                if 0 <= nxt_r < len(grid) and 0 <= nxt_c < len(grid[0]):\n                    if ((grid[nxt_r][nxt_c] == 0 and (nxt_r, nxt_c, obst_rem) not in visited) or\n                        grid[nxt_r][nxt_c] == 1 and obst_rem > 0 and (nxt_r, nxt_c, obst_rem-1) not in visited):\n                        if nxt_r == len(grid) - 1 and nxt_c == len(grid[0]) - 1:\n                            return steps + 1\n                        else:\n                            visited.add((nxt_r, nxt_c, obst_rem-grid[nxt_r][nxt_c]))\n                            q.append((nxt_r, nxt_c, obst_rem-grid[nxt_r][nxt_c], steps+1))\n        return -1\n", "from collections import deque\nfrom heapq import heappush\nfrom heapq import heappop\n\n_DIRS = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return 0\n        \n        m, n = len(grid), len(grid[0])\n        if k >= m + n - 2:\n            return m + n - 2\n        \n        queue = []\n        visited = set()\n        queue.append((0, k, 0, 0))\n        visited.add((0, 0, k))\n        \n        while queue:\n            cost, ck, ci, cj = heappop(queue)\n            if (ci, cj) == (m - 1, n - 1):\n                return cost\n            for di, dj in _DIRS:\n                newi, newj = ci + di, cj + dj\n                if not 0 <= newi < m or not 0 <= newj < n:\n                    continue\n                if grid[newi][newj] == 1 and ck > 0 and (newi, newj, ck - 1) not in visited:\n                    heappush(queue, (cost + 1, ck - 1, newi, newj))\n                    visited.add((newi, newj, ck - 1))\n                if grid[newi][newj] == 0 and (newi, newj, ck) not in visited:\n                    heappush(queue, (cost + 1, ck, newi, newj))\n                    visited.add((newi, newj, ck))\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        dirs=[(0,1),(0,-1),(1,0),(-1,0)]\n        m,n=len(grid),len(grid[0])\n        seen=[[float('inf')]*n for _ in range(m)]\n        q=[(0,0,0)]\n        step=0\n        seen[0][0]=0\n        while q:\n            size=len(q)\n            for _ in range(size):\n                x,y,o=q.pop(0)\n                if x==m-1 and y==n-1:\n                    return step\n                for dx,dy in dirs:\n                    nx,ny=x+dx,y+dy\n                    if nx<0 or ny<0 or nx>=m or ny>=n:\n                        continue\n                    no=o+grid[nx][ny]\n                    if no>=seen[nx][ny] or no>k:\n                        continue\n                    seen[nx][ny]=no\n                    q.append((nx,ny,no))\n            step+=1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        '''\n        Iterative.\n        Shortest path = BFS\n        '''\n        M, N = len(grid), len(grid[0])\n        if not grid or not grid[0] or (grid[0][0] and k == 0):\n            return -1\n        minpath = 0\n        queue = collections.deque([(0,0,k)])\n        seen = {(0,0): k}\n        while queue:\n            for _ in range(len(queue)):\n                i,j,K = queue.popleft()\n                # print(i,j,K)\n                if i == M-1 and j == N-1:\n                    return minpath\n                if grid[i][j]: \n                    K -= 1\n                for r,c in [(i+1,j), (i-1,j), (i,j+1), (i,j-1)]:\n                    if not(0<=r<M) or not(0<=c<N) or (grid[r][c] and not K):\n                        continue\n                    if (r,c) in seen and seen[(r,c)] >= K:\n                        continue\n                    seen[r,c] = K\n                    queue.append((r,c,K))\n            minpath += 1\n            # print('minpath', minpath)\n        return -1\n        \n        \n        '''\n        Recursive with memo\n        '''\n        M,N = len(grid), len(grid[0])\n        memo = {}\n        def path(i,j,k):\n            if not(0<=i<M) or not(0<=j<N) or (grid[i][j] == 1 and k == 0) or grid[i][j] == -1:\n                return float('inf')\n            if i == M-1 and j == N-1:\n                    return 0\n            if (i,j,k) not in memo:\n                if grid[i][j] == 1: \n                    k -= 1\n                # Mark as seen\n                orig, grid[i][j] = grid[i][j], -1\n                res = float('inf')\n                for r, c in [(i+1, j), (i-1,j), (i,j-1), (i,j+1)]:\n                    res = min(res, path(r,c,k))\n                grid[i][j] = orig\n                memo[(i,j,k)] = res + 1\n            return memo[(i,j,k)]\n        \n        min_path = path(0,0,k)\n        \n        return min_path if min_path != float('inf') else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque([[0, 0, 0, 0]])\n        n, m = len(grid), len(grid[0])\n        minObs = [0] * n\n        move = [[1, 0], [-1, 0], [0, -1], [0, 1]]\n        \n        for i in range(n):\n            minObs[i] = [1e9] * m\n        \n        while len(queue):\n            r, c, obs, steps = queue.popleft()\n        \n            # if obs > minObs[r][c]:\n            #     continue\n                \n            if r == n-1 and c == m-1:\n                return steps\n\n            for mR, mC in move:\n                nextR = r + mR\n                nextC = c + mC\n                \n                if 0 <= nextR < n and 0 <= nextC < m and obs+grid[nextR][nextC] <= k and obs+grid[nextR][nextC] < minObs[nextR][nextC]:\n                    minObs[nextR][nextC] = obs+grid[nextR][nextC]\n                    queue.append([nextR, nextC, obs+grid[nextR][nextC], steps+1])\n        \n        return -1 \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m,n = len(grid), len(grid[0])\n        \n        Queue = deque([(0,0,0,k)])\n        visited = {}\n        visited[(0,0)]=k\n        while Queue:\n            i,j,d,lifeline = Queue.popleft()\n            \n            if i==m-1 and j==n-1:\n                return d\n            \n            for x,y in [(i+1,j),(i-1,j),(i,j-1),(i,j+1)]:\n                if x>=0 and x<m and y>=0 and y<n:\n                    if grid[x][y]==1:\n                        if lifeline>0 and ((x,y) not in visited or visited[(x,y)]<lifeline-1):\n                            visited[(x,y)] = lifeline-1\n                            Queue.append((x,y,d+1,lifeline-1))\n                    else:\n                        if (x,y) not in visited or visited[(x,y)]<lifeline:\n                            visited[(x,y)] = lifeline\n                            Queue.append((x,y,d+1,lifeline))\n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        '''\n        Iterative.\n        Shortest path = BFS\n        '''\n        M, N = len(grid), len(grid[0])\n        minpath = 0\n        queue = collections.deque([(0,0,k)])\n        seen = {(0,0): k}\n        while queue:\n            for _ in range(len(queue)):\n                i,j,K = queue.popleft()\n                if i == M-1 and j == N-1:\n                    return minpath\n                if grid[i][j]: \n                    K -= 1\n                for r,c in [(i+1,j), (i-1,j), (i,j+1), (i,j-1)]:\n                    if not(0<=r<M) or not(0<=c<N) or (grid[r][c] and not K):\n                        continue\n                    if (r,c) in seen and seen[(r,c)] >= K:\n                        continue\n                    seen[r,c] = K\n                    queue.append((r,c,K))\n            minpath += 1\n            # print('minpath', minpath)\n        return -1\n        \n        \n        '''\n        Recursive with memo\n        '''\n        M,N = len(grid), len(grid[0])\n        memo = {}\n        def path(i,j,k):\n            if not(0<=i<M) or not(0<=j<N) or (grid[i][j] == 1 and k == 0) or grid[i][j] == -1:\n                return float('inf')\n            if i == M-1 and j == N-1:\n                    return 0\n            if (i,j,k) not in memo:\n                if grid[i][j] == 1: \n                    k -= 1\n                # Mark as seen\n                orig, grid[i][j] = grid[i][j], -1\n                res = float('inf')\n                for r, c in [(i+1, j), (i-1,j), (i,j-1), (i,j+1)]:\n                    res = min(res, path(r,c,k))\n                grid[i][j] = orig\n                memo[(i,j,k)] = res + 1\n            return memo[(i,j,k)]\n        \n        min_path = path(0,0,k)\n        \n        return min_path if min_path != float('inf') else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        H, W = len(grid), len(grid[0])\n        if k >= H+W-3: return H+W-2 # we can always travel along the sides\n        \n        step = 0\n        node_list = [(0, 0, k)]\n        visited = set()\n        while node_list:\n            new_list = []\n            for node in node_list:\n                if node in visited: continue\n                visited.add(node)\n                x, y, k_remains = node\n                if x == H-1 and y == W-1: return step\n                for i, j in [[x-1, y], [x+1, y], [x, y-1], [x, y+1]]:\n                    if i < 0 or i >= H or j < 0 or j >= W:\n                        continue\n                    # accessible path\n                    if grid[i][j] == 0:\n                        new_list.append((i, j, k_remains))\n                    # obstacle\n                    elif grid[i][j] == 1 and k_remains > 0:\n                        new_list.append((i, j, k_remains-1))\n            \n            step += 1\n            node_list = new_list\n        \n        return -1\n                    \n                    \n            \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m,n = len(grid), len(grid[0])\n        \n        Queue = deque([(0,0,0,k)])\n        visited = {}\n        visited[(0,0)]=k\n        while Queue:\n            i,j,d,lifeline = Queue.popleft()\n            \n            if i==m-1 and j==n-1:\n                return d\n            \n            for x,y in [(i+1,j),(i-1,j),(i,j-1),(i,j+1)]:\n                if x>=0 and x<m and y>=0 and y<n:\n                    if grid[x][y]==1:\n                        if lifeline>0 and ((x,y) not in visited or visited[(x,y)]<lifeline-1):\n                            visited[(x,y)] = lifeline-1\n                            Queue.append((x,y,d+1,lifeline-1))\n                    else:\n                        if (x,y) not in visited or visited[(x,y)]<lifeline:\n                            visited[(x,y)] = lifeline\n                            Queue.append((x,y,d+1,lifeline))\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        R, C = len(grid), len(grid[0])\n        if R == 1 and C == 1:\n            return 0\n        cur = [(0, 0, 0, k)]\n        step = 0\n        seen = {(0,0):k}\n        while cur:\n            nex = []\n            for s, r, c, remain in cur:\n                for rp, cp in [(r-1, c), (r+1, c), (r, c-1), (r, c+1)]:\n                    if 0 <= rp < R and 0 <= cp < C:\n                        if rp == R - 1 and cp == C - 1:\n                            return s + 1\n                        next_remain = remain if grid[rp][cp] == 0 else remain - 1\n                        if next_remain < 0:\n                            continue\n                        if seen.get((rp,cp), -1) < next_remain:\n                            seen[(rp, cp)] = next_remain\n                            nex.append((s+1, rp, cp, next_remain))\n            cur = nex\n        return -1\n            \n                        \n                    \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        seen = [[float('inf')] * len(grid[0]) for _ in range(len(grid))]\n        seen[0][0] = 0\n        queue = collections.deque([(0, 0, 0)])\n        step = 0\n        direct = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n        while queue:\n            length = len(queue)\n            for _ in range(length):\n                x, y, u = queue.popleft()\n                if x == len(grid) - 1 and y == len(grid[0]) - 1:\n                    return step\n                for i, j in direct:\n                    newx, newy, newu = i + x, y + j, u\n                    if newx < 0 or newy < 0 or newx > len(grid) - 1 or newy > len(grid[0]) - 1:\n                        continue\n                    if grid[newx][newy] == 1:\n                        newu += 1\n                    if newu > k or newu >= seen[newx][newy]:\n                        continue\n                    seen[newx][newy] = newu\n                    queue.append((newx, newy, newu))\n            step += 1\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # m*n*k grid\n        # minimum steps for each of k values, \n        # bfs - enque if same cell isn't visited\n        # of same cell with lower k, but higher cost isn't recorded\n        m, n = len(grid), len(grid[0])\n        q = collections.deque()\n        q.append((0,0,0,0))\n        explored = {(0,0):0}\n        ans = 1 << 31 - 1\n        while q:\n            i, j, obs, dist = q.popleft()\n            # print(i,j,obs,dist)\n            if i == m-1 and j == n-1:\n                ans = min(ans, dist)\n            for di, dj in ((i+1, j), (i-1, j), (i, j+1), (i, j-1)):\n                if 0 <= di < m and 0 <= dj < n:\n                    if ((di, dj) not in explored or\n                        explored[(di,dj)] > obs + grid[di][dj]) and obs + grid[di][dj] <= k:\n                            explored[(di,dj)] = obs + grid[di][dj]\n                            q.append((di, dj, obs+grid[di][dj], dist+1))\n\n        return ans if ans < m*n else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = set()\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and (ii, jj, k) not in seen:\n                            seen.add((ii, jj, k))\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and (ii, jj, k-1) not in seen:\n                            seen.add((ii, jj, k-1))\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        K = k\n        q = []\n        q.append((0, 0, K, 0))\n        seen = {}\n        \n        while q:\n            q2 = []\n            for i, j, k, c in q:\n                if i == m-1 and j == n-1:\n                    return c\n                for ii, jj in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):\n                    if 0 <= ii < m and 0 <= jj < n:\n                        if grid[ii][jj] == 0 and ((ii, jj) not in seen or k > seen[(ii, jj)]):\n                            seen[(ii, jj)] = k\n                            q2.append((ii, jj, k, c+1))\n                        if grid[ii][jj] == 1 and k > 0 and ((ii, jj) not in seen or k-1 > seen[(ii, jj)]):\n                            seen[(ii, jj)] = k-1\n                            q2.append((ii, jj, k-1, c+1))\n            q = q2\n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        q = collections.deque([[0, 0, 0]])    # row, col, num of obstables met so far\n        visited = {(0, 0): 0}                 # row, col   =>   num of obstables met so far\n        steps = 0\n        \n        while q:\n            size = len(q)\n            for _ in range(size):\n                r, c, obs = q.popleft()\n                if obs > k: continue\n                if r == m - 1 and c == n - 1: \n                    return steps\n                for r2, c2 in [[r+1, c], [r-1, c], [r, c+1], [r, c-1]]:\n                    if 0 <= r2 < m and 0 <= c2 < n:\n                        next_obs = obs + 1 if grid[r2][c2] == 1 else obs\n                        if next_obs < visited.get((r2, c2), float('inf')):\n                            visited[(r2, c2)] = next_obs\n                            q.append([r2, c2, next_obs])\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid:\n            return -1\n        m, n = len(grid), len(grid[0])\n        visited = defaultdict(int)\n\n        q, nq, step = deque([(0, 0, k)]), deque(), 0\n        \n        while q:\n            x, y, chance = q.popleft()\n            \n            if (x, y) == (m-1, n-1):\n                return step\n            \n            for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:\n                xx, yy = x+dx, y+dy\n                if 0 <= xx < m and 0 <= yy < n:\n                    chance_left = chance - grid[xx][yy]\n                    if chance_left < 0: continue\n                    if (xx, yy) not in visited or visited[(xx,yy)] < chance_left:\n                        visited[(xx, yy)] = chance_left\n                        nq.append((xx, yy, chance_left))\n            \n            if not q:\n                q, nq = nq, deque()\n                step += 1\n        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \\\"\\\"\\\"\n        BFS\n        \n        visited: {i, j, # of breaks}\n        \n        q = [(i, j, # of breaks, # of steps)]\n        generate neighbor:\n            if grid[nei] == 1:\n                (i, j, # of breaks + 1)\n                discard if # of breaks + 1 > k\n            else:\n                (i, j, # of breaks)\n        \\\"\\\"\\\"\n        q = deque([(0, 0, grid[0][0], 0)])\n        visited = {(0, 0): grid[0][0]}\n        m, n = len(grid), len(grid[0])\n        if m == n == 1:\n            return 0\n        while q:\n            i, j, breakNumber, steps = q.popleft()\n            for ni, nj in [[i+1, j], [i-1, j], [i, j+1], [i, j-1]]:\n                if 0 <= ni < m and 0 <= nj < n:\n                    nBreaks = breakNumber + grid[ni][nj]\n                    if nBreaks > k:\n                        continue\n                    if (ni, nj) == (m-1, n-1):\n                        return steps + 1\n                    if (ni, nj) not in visited or visited[(ni, nj)] > nBreaks:\n                        visited[(ni, nj)] = nBreaks\n                        q.append((ni, nj, nBreaks, steps + 1))\n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        rows, cols = len(grid), len(grid[0])\n        \n        if k >= rows + cols - 3:\n            return rows+cols-2\n        \n        q, seen = deque([(0,0,0,0)]), set()\n        seen.add((0,0,0))\n        \n        while q:\n            i, j, rem, curr_path = q.popleft()\n            if i == rows-1 and j == cols-1:\n                return curr_path\n            \n            for m, n in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:\n                if 0<=m<rows and 0<=n<cols and ((m,n,rem) not in seen) and rem+grid[m][n]<=k:\n                    q.append((m, n, rem+grid[m][n], curr_path+1))\n                    seen.add((m,n,rem+grid[m][n]))\n            \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        d = [(0, 1), (0, -1), (1, 0), (-1, 0)]\n        q = collections.deque()\n        v = {}\n        q.append((0, 0, k, 0))  # x, y , k and step\n\n        while q:\n            x, y, z, s = q.popleft()\n            v[(x,y)] = z\n            if x == (m - 1) and y == (n - 1):\n                return s\n            for dx, dy in d:\n                nx , ny = x+dx, y+dy\n                if nx >= 0 and nx < m and ny >= 0 and ny < n and ((\n                nx,ny) not in v or v[(nx,ny)]<z-grid[nx][ny]):\n                    if nx == m - 1 and ny == n - 1:\n                        return s + 1\n                    if (grid[nx][ny] == 1 and z > 0):\n                        q.append((nx, ny , z - 1, s + 1))\n                        v[(nx ,ny)]=z-1\n                    elif grid[nx][ny] == 0:\n                        q.append((nx, ny, z, s + 1))\n                        v[(nx ,ny )] = z\n                    else:\n                        continue\n\n        return -1", "MAX = 1601\nfrom collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], K: int) -> int:\n        m,n = len(grid), len(grid[0])\n        #dp = [[{} for c in range(n)] for r in range(m)]\n        maxK = [[-1]*n for _ in range(m)]\n        \n        q = deque([(0,0,0,K)])\n        \n        while q:\n            i,j,d,k = q.popleft()\n            if i==m-1 and j==n-1: \n                return d\n            if k <= maxK[i][j]:\n                continue\n            maxK[i][j] = max(maxK[i][j], k)\n            for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                if 0<=x<m and 0<=y<n and k-grid[x][y]>=0:\n                    q.append((x,y,d+1,k-grid[x][y]))\n        \n        return -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        # we have shortest path in unweighted graph, so we use bfs\n        # we store obstacles here and remove if we can until we reach to end\n        if not grid:\n            return 0\n        \n        queue = deque()\n        visited = dict()\n        if grid[0][0] == 1:\n            queue.append((0, 0, k-1, 0))\n            visited[0, 0] = k-1\n        else:\n            queue.append((0, 0, k, 0))\n            visited[0, 0] = k\n        \n        n, m = len(grid), len(grid[0])\n        while queue:\n            x, y, obst, path = queue.popleft()\n            if obst < 0:\n                continue\n            if x == n-1 and y == m-1:\n                if grid[x][y] == 0 or (grid[x][y] == 1 and obst >= 1): # if end is an obstacle, check if we can accept it\n                    return path\n                # we can keep going to check for another path\n            \n            for x_path, y_path in [(x+1, y), (x-1, y), (x, y-1), (x, y+1)]:\n                # continue if out of bounds OR number of obstacles to this point earlier is higher, then we prune\n                if x_path < 0 or y_path < 0 or x_path >= n or y_path >= m or \\\\\n                ((x_path, y_path) in visited and visited[(x_path, y_path)] >= obst) \\\\\n                or (grid[x_path][y_path] == 1 and obst == 0):\n                    continue\n                \n                if grid[x_path][y_path] == 1:\n                    visited[(x_path, y_path)] = obst-1\n                    queue.append((x_path, y_path, obst-1, path+1))\n                else:\n                    visited[(x_path, y_path)] = obst\n                    queue.append((x_path, y_path, obst, path+1))\n        return -1\n                                                                              \n                    \n                \n            \n        \n        ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n = len(grid)\n        m = len(grid[0])\n        \n        if n == 1 and m == 1:\n            if grid[0][0] == 0:\n                return 0\n            return -1 if k < 1 else 0\n        \n        visited = [[False] * m for i in range(n)]\n        moves = [\n            [0, 1],\n            [1, 0],\n            [-1, 0],\n            [0, -1]\n        ]\n        \n        q = []\n        \\\"\\\"\\\"\n        (x, y, k, steps)\n        \\\"\\\"\\\"\n        q.append((0, 0, k, 0))\n        \n        while len(q) != 0:\n            curr = q.pop(0)\n            \n            if (curr[0], curr[1]) == (m - 1, n - 1):\n                return curr[3]\n            \n            for move in moves:\n                newX = curr[0] + move[0]\n                newY = curr[1] + move[1]\n                \n                if newX >= m or newY >= n or newX < 0 or newY < 0:\n                    continue\n                \n                if grid[newY][newX] == 1 and curr[2] == 0:\n                    continue\n                \n                newK = curr[2] if grid[newY][newX] == 0 else curr[2] - 1\n                if visited[newY][newX] != False:\n                    old = visited[newY][newX]\n                    if old[2] < newK:\n                        newMove = (newX, newY, newK, curr[3] + 1)\n                        q.append(newMove)\n                        visited[newY][newX] = newMove\n                else:\n                    newMove = (newX, newY, newK, curr[3] + 1)\n                    q.append(newMove)\n                    visited[newY][newX] = newMove\n        \n        return -1", "from collections import defaultdict\nclass Solution:\n    def shortestPath(self, A: List[List[int]], k: int) -> int:\n        dic = defaultdict(list)\n        nbs = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        m, n = len(A), len(A[0])\n        st = [(0, 0, 0)]\n        target = m * n - 1\n        if target == 0: return 0\n        while st:\n            t = []\n            for a, b, c in st:\n                x, y = a // n, a % n\n                for i, j in nbs:\n                    nx, ny = x + i, y + j\n                    if 0 <= nx < m and 0 <= ny < n:\n                        p = nx * n + ny\n                        cost = c + 1 if A[nx][ny] else c\n                        if p == target and cost <= k:\n                            return b + 1\n                        if p not in dic or cost < dic[p][-1][-1]:\n                            dic[p].append([b + 1, cost])\n                            t.append((p, b + 1, cost))\n            st = t\n        return -1", "from collections import deque\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        if grid[0][0] == 1:\n            k -= 1\n            \n        q = deque([(0,0,k,0)])\n        visited = {}\n        \n        while len(q) > 0:\n            r, c, avail, path = q.popleft()\n            if r == len(grid)-1 and c == len(grid[0])-1:\n                return path\n            \n            for dr, dc in [(0,1), (0,-1), (1,0), (-1,0)]:\n                nr, nc = r+dr, c+dc\n                \n                if nr < 0 or nr >= len(grid) or nc < 0 or nc >= len(grid[0]):\n                    continue\n                    \n                if grid[nr][nc] == 1 and not avail:\n                    continue\n                \n                if (nr, nc) in visited and avail <= visited[(nr, nc)]:\n                    continue\n                \n                visited[(nr, nc)] = avail\n                if grid[nr][nc] == 0:\n                    q.append((nr, nc, avail, path+1))\n                elif avail > 0:\n                    q.append((nr, nc, avail-1, path+1))\n        \n        return -1\n\n                \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        seen = [[float('inf')] * len(grid[0]) for _ in range(len(grid))]\n        queue = collections.deque([(0, 0, 0)])\n        step = 0\n        direct = [(0, 1), (1, 0), (0, -1), (-1, 0)]\n        while queue:\n            length = len(queue)\n            for _ in range(length):\n                x, y, u = queue.popleft()\n                if x == len(grid) - 1 and y == len(grid[0]) - 1:\n                    return step\n                if x < 0 or y < 0 or x > len(grid) - 1 or y > len(grid[0]) - 1:\n                    continue\n                if grid[x][y] == 1:\n                    u += 1\n                if u > k or u >= seen[x][y] :\n                    continue\n                seen[x][y] = u\n                for i, j in direct:\n                    queue.append((x + i, y + j, u))\n            step += 1\n        return -1", "from queue import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def can_visit(grid, x, y, k, visited, queue, n_steps):\n            #print (\\\"Trying to visit {}, {}, {}\\\".format(x, y, k))\n            if (grid[x][y] == 0 or k > 0) :\n                #print (\\\"Visiting {}, {}, {}\\\".format(x, y, k))\n                if grid[x][y] > 0:\n                    #print (\\\"Obstacle removal {}, {}, {}\\\".format(x, y, k))\n                    k -= 1\n                    \n                # Add to queue only if not visited. Or if visited but current \n                # k is higher so there's more chances to still remove obstacles.\n                # Or if we visited but now we come here with less steps\n                if (x, y) not in visited or k > visited[(x, y)][0] or n_steps < visited[(x, y)][1]:\n                    visited[(x, y)] = (k, n_steps)\n                    queue.append((x, y, k, n_steps))\n        \n        rows = len(grid)\n        cols = len(grid[0])\n        x = 0\n        y = 0\n        queue = deque()\n        visited = {}\n        n_steps = 0\n        visited[(x, y)] = (k, n_steps)\n        queue.append((x, y, k, n_steps))\n        min_steps = float(inf)\n        \n        while len(queue) > 0:\n            x, y, k_remaining, n_steps = queue.popleft()\n            #print (x, y, k_remaining, n_steps)\n            \n            if x == rows - 1 and y == cols - 1:\n                min_steps = min(n_steps, min_steps)\n                \n            n_steps += 1\n            \n            if x > 0:\n                left_x = x - 1\n                can_visit(grid, left_x, y, k_remaining, visited, queue, n_steps)\n            \n            if y > 0:\n                down_y = y - 1\n                can_visit(grid, x, down_y, k_remaining, visited, queue, n_steps)\n                \n            if x < rows - 1:\n                right_x = x + 1\n                can_visit(grid, right_x, y, k_remaining, visited, queue, n_steps)\n            \n            if y < cols - 1:\n                up_y = y + 1\n                can_visit(grid, x, up_y, k_remaining, visited, queue, n_steps)\n            \n        return min_steps if min_steps != inf else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        '''\n        Iterative.\n        Shortest path = BFS\n        '''\n        M, N = len(grid), len(grid[0])\n        if not grid or not grid[0] or (grid[0][0] and k == 0):\n            return -1\n\n        def outOfBound(r, c):\n            return not(0<=r<M) or not(0<=c<N)\n        \n        def wallButRunsOutOfK(r, c, K):\n            return (grid[r][c] and not K)\n        \n        def seenWithLargerK(r,c,K,seen):\n            return (r,c) in seen and seen[(r,c)] >= K\n        \n        queue = collections.deque([(0,0,k)])\n        seen = {(0,0): k}\n        minpath = 0\n        \n        while queue:\n            for _ in range(len(queue)):\n                i,j,K = queue.popleft()\n                if i == M-1 and j == N-1:\n                    return minpath\n                if grid[i][j]: \n                    K -= 1\n                for r,c in [(i+1,j), (i-1,j), (i,j+1), (i,j-1)]:\n                    if outOfBound(r,c) or wallButRunsOutOfK(r,c,K) or seenWithLargerK(r,c,K,seen):\n                        continue\n                    # update the best k value so far for this position\n                    seen[r,c] = K\n                    queue.append((r,c,K))\n            minpath += 1\n            # print('minpath', minpath)\n        return -1\n     \n        '''\n        Recursive with memo\n        '''\n        M,N = len(grid), len(grid[0])\n        memo = {}\n        def path(i,j,k):\n            if not(0<=i<M) or not(0<=j<N) or (grid[i][j] == 1 and k == 0) or grid[i][j] == -1:\n                return float('inf')\n            if i == M-1 and j == N-1:\n                    return 0\n            if (i,j,k) not in memo:\n                if grid[i][j] == 1: \n                    k -= 1\n                # Mark as seen\n                orig, grid[i][j] = grid[i][j], -1\n                res = float('inf')\n                for r, c in [(i+1, j), (i-1,j), (i,j-1), (i,j+1)]:\n                    res = min(res, path(r,c,k))\n                grid[i][j] = orig\n                memo[(i,j,k)] = res + 1\n            return memo[(i,j,k)]\n        \n        min_path = path(0,0,k)\n        \n        return min_path if min_path != float('inf') else -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rowlen = len(grid)\n        collen = len(grid[0])     \n        \n        if k >= rowlen + collen - 3:\n            return rowlen + collen - 2\n        \n        visited = set()\n        visited.add((0,0,k))\n        \n        q = deque([(0,0,k, 0)])\n        \n        def get_nexts(x,y):\n            return [(nx,ny) for (nx,ny) in [(x+1,y), (x-1, y), (x, y+1), (x, y-1)] if 0<=nx<rowlen and 0<=ny<collen]\n        \n        while q:\n            x,y,k,path_count = q.popleft()       \n            \n            if (x,y) == (rowlen-1, collen-1): return path_count\n                        \n            nexts = get_nexts(x,y)\n            \n            for nx,ny in nexts:                \n                if grid[nx][ny] == 1 and not k: continue\n                if grid[nx][ny] == 1 and (nx,ny,k-1) in visited: continue\n                if grid[nx][ny] == 0 and (nx,ny,k) in visited: continue\n                    \n                if grid[nx][ny] == 1:\n                    visited.add((nx,ny,k-1))\n                    q.append((nx,ny,k-1,path_count+1))\n                else:\n                    if (nx,ny) == (rowlen-1, collen-1): return path_count+1\n                    visited.add((nx,ny,k))\n                    q.append((nx,ny,k,path_count+1))                \n        \n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        '''\n        Iterative.\n        Shortest path = BFS\n        '''\n        M, N = len(grid), len(grid[0])\n        if not grid or not grid[0] or (grid[0][0] and k == 0):\n            return -1\n        minpath = 0\n        queue = collections.deque([(0,0,k)])\n        seen = {(0,0): k}\n        \n        def outOfBound(r, c):\n            return not(0<=r<M) or not(0<=c<N)\n        \n        def wallButRunsOutOfK(r, c, K):\n            return (grid[r][c] and not K)\n        \n        def seenWithLargerK(r,c,K,seen):\n            return (r,c) in seen and seen[(r,c)] >= K\n        \n        while queue:\n            for _ in range(len(queue)):\n                i,j,K = queue.popleft()\n                if i == M-1 and j == N-1:\n                    return minpath\n                if grid[i][j]: \n                    K -= 1\n                for r,c in [(i+1,j), (i-1,j), (i,j+1), (i,j-1)]:\n                    if outOfBound(r, c) or wallButRunsOutOfK(r,c,K) or seenWithLargerK(r,c,K,seen):\n                        continue\n                    seen[r,c] = K\n                    queue.append((r,c,K))\n            minpath += 1\n            # print('minpath', minpath)\n        return -1\n    \n        \n        \n        \n        '''\n        Recursive with memo\n        '''\n        M,N = len(grid), len(grid[0])\n        memo = {}\n        def path(i,j,k):\n            if not(0<=i<M) or not(0<=j<N) or (grid[i][j] == 1 and k == 0) or grid[i][j] == -1:\n                return float('inf')\n            if i == M-1 and j == N-1:\n                    return 0\n            if (i,j,k) not in memo:\n                if grid[i][j] == 1: \n                    k -= 1\n                # Mark as seen\n                orig, grid[i][j] = grid[i][j], -1\n                res = float('inf')\n                for r, c in [(i+1, j), (i-1,j), (i,j-1), (i,j+1)]:\n                    res = min(res, path(r,c,k))\n                grid[i][j] = orig\n                memo[(i,j,k)] = res + 1\n            return memo[(i,j,k)]\n        \n        min_path = path(0,0,k)\n        \n        return min_path if min_path != float('inf') else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n = len(grid)\n        m = len(grid[0])\n        \n        if n == 1 and m == 1:\n            if grid[0][0] == 0:\n                return 0\n            return -1 if k < 1 else 0\n        \n        visited = [[False] * m for i in range(n)]\n        moves = [\n            [0, 1],\n            [1, 0],\n            [-1, 0],\n            [0, -1]\n        ]\n        \n        q = []\n        \\\"\\\"\\\"\n        (x, y, k, steps)\n        \\\"\\\"\\\"\n        q.append((0, 0, k, 0))\n        \n        while len(q) != 0:\n            curr = q.pop(0)\n            \n            if (curr[0], curr[1]) == (m - 1, n - 1):\n                return curr[3]\n            \n            for move in moves:\n                newX = curr[0] + move[0]\n                newY = curr[1] + move[1]\n                \n                if newX >= m or newY >= n or newX < 0 or newY < 0:\n                    continue\n                \n                if grid[newY][newX] == 1 and curr[2] == 0:\n                    continue\n                \n                newK = curr[2] if grid[newY][newX] == 0 else curr[2] - 1\n                if visited[newY][newX] != False:\n                    old = visited[newY][newX]\n                    if old[2] < newK:\n                        newMove = (newX, newY, newK, curr[3] + 1)\n                        q.append(newMove)\n                        visited[newY][newX] = newMove\n                else:\n                    newMove = (newX, newY, newK, curr[3] + 1)\n                    q.append(newMove)\n                    visited[newY][newX] = newMove\n        \n        if not visited[n - 1][m - 1]:\n            return -1\n        return visited[n - 1][m - 1][3]", "from heapq import heappop, heappush\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return -1\n        \n        deltas = ((-1, 0), (0, 1), (0, -1), (1, 0))\n        n, m = len(grid), len(grid[0])\n        \n        source, target = (0, 0), (n-1, m-1)\n        \n        # All nodes which have been reached. This is the earliest to reach this node according to steps needed\n        queue = deque([(0, source, 0)])\n        \n        # Record with how many obstacles removed has the current node been seen\n        seen = {source: 0}\n        \n        while queue:\n            usedK, currPos, steps = queue.popleft()\n            if currPos == target:\n                return steps\n            for delta_x, delta_y in deltas:\n                x, y = currPos[0] + delta_x, currPos[1] + delta_y\n                if x >= 0 and x < n and y >= 0 and y < m:\n                    if (x, y) not in seen or seen[(x, y)] > usedK:\n                        # Either not visited prev, or can visit with fewer obstacles\n                        # There are potentially two entries in the queue for the same node with different obstacles used\n                        if grid[x][y] == 0:\n                            seen[(x, y)] = usedK\n                            # Can enter here\n                            queue.append((usedK, (x, y), steps+1))\n                        elif usedK < k:\n                            # Mark one obstacle removed and continue\n                            seen[(x, y)] = usedK + 1\n                            queue.append((usedK+1, (x, y), steps+1))\n        \n        return -1\n", "from heapq import heappop, heappush\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid or not grid[0]:\n            return -1\n        \n        deltas = ((-1, 0), (0, 1), (0, -1), (1, 0))\n        n, m = len(grid), len(grid[0])\n        \n        source, target = (0, 0), (n-1, m-1)\n        \n        # All nodes which have been reached. This is the earliest to reach this node\n        # Priority as per the number of obstacles removed within nodes at the same level. This ensures that if a new node is reachable from two nodes of the current level, the new node is marked reached from the one where fewer obstacles were removed (since number of steps is going to remain in both cases)\n        queue = deque([(0, source, 0)])\n        # Note the next set of nodes reachable from current level\n        # nxt = []\n        seen = {source: 0}\n        \n        while queue:\n            usedK, currPos, steps = queue.popleft()\n            if currPos == target:\n                return steps\n            for delta_x, delta_y in deltas:\n                x, y = currPos[0] + delta_x, currPos[1] + delta_y\n                if x >= 0 and x < n and y >= 0 and y < m:\n                    if (x, y) not in seen or seen[(x, y)] > usedK:\n                        if grid[x][y] == 0:\n                            seen[(x, y)] = usedK\n                            # Can enter here\n                            queue.append((usedK, (x, y), steps+1))\n                        elif usedK < k:\n                            seen[(x, y)] = usedK + 1\n                            queue.append((usedK+1, (x, y), steps+1))\n        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        n = len(grid)\n        m = len(grid[0])\n        dist = []\n        for i in range(n):\n            dist.append([])\n            for j in range(m):\n                dist[i].append([-1,-1])\n        queue = []\n        queue.append([0, 0, 0, k])\n        dist[0][0][0] = 0\n        dist[0][0][1] = k\n        while queue:\n            top = queue.pop(0)\n            dis = top[0]\n            i = top[1]\n            j = top[2]\n            if i==n-1 and j ==m-1:\n                return dis\n            res = top[3]\n            print(i, j, dis, res)\n            for x, y in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]:\n                if x >= 0 and y >= 0 and x < n and y < m:\n                    nk = res - int(grid[x][y] == 1)\n                    if nk >= 0:\n                        if dist[x][y][0] == -1 or nk > dist[x][y][1]:\n                            dist[x][y][0] = dis+1\n                            dist[x][y][1] = nk\n                            queue.append([dis+1, x, y, nk])\n        \n        return dist[n-1][m-1][0]", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        q = collections.deque()\n        q.append((0,0,0,k))\n        visited={}\n        if not grid:\n            return -1\n        m,n=len(grid),len(grid[0])\n        while q:\n            x,y,d,lifeline=q.popleft()\n            if x==m-1 and y==n-1:\n                return d\n            \n            for i,j in [(x+1,y),(x-1,y),(x,y+1),(x,y-1)]:\n                if 0<=i<m and 0<=j<n:\n                    if grid[i][j]==1:\n                        if lifeline>=1:\n                            if (i,j) in visited:\n                                if visited[(i,j)]<lifeline-1:\n                                    q.append((i,j,d+1,lifeline-1))\n                                    visited[(i,j)]=lifeline-1\n                            else:\n                                q.append((i,j,d+1,lifeline-1))\n                                visited[(i,j)]=lifeline-1\n                    else:\n                        if (i,j) in visited:\n                            if visited[(i,j)]<lifeline:\n                                q.append((i,j,d+1,lifeline))\n                                visited[(i,j)]=lifeline\n                        else:\n                            q.append((i,j,d+1,lifeline))\n                            visited[(i,j)]=lifeline\n                            \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        \n        path_store = deque([((0,0), 0, k)])\n        \n        seen = {}\n        while path_store:\n            temp = path_store.pop()\n            s, t = temp[0]\n            if s == m-1 and t == n-1:\n                return temp[1]\n            for i, j in [(s+1, t), (s, t+1), (s-1, t), (s, t-1)]:\n                if i < 0 or i >= m or j < 0 or j >= n or (k == 0 and grid[i][j] == 1) or seen.get((i,j), -1) >= temp[2] - (grid[i][j]==1):\n                    continue\n                seen[(i,j)] = temp[2] - (grid[i][j]==1)\n                path_store.appendleft(((i,j), temp[1]+1, seen[(i,j)]))\n        return -1", "\\\"\\\"\\\"\ntry permutation removal of k obstacles and find the shortest way in each removal\n\ntime complexy = (n ^ k) * size(board)\n\ndp[row][col][k] = to get (row, col) with removing k obstacles, shortest cost\n\n0110000\n0110110\n0000110\n\n2 steps , removing 2 obstacles\n9 steps , removing 0 obstacle\n\nbfs (0, 0, 0, 0) # row, col, number removed obstacle, step\n(1, 0, 0, 1)\nbfs -> row, col\ndef bfs(grid, max_k):\n    row = len(grid)\n    if not row:\n        return -1\n    col = len(grid[0])\n    if not col:\n        return -1\n        \n    cost = [[[-1 for _ in range(k + 1)] for _ in range(col)] for _ in range(row)]\n    \n    q = deque()\n    q.append((0, 0, 0, 0))\n    while q:\n        r, c, step, k = q.popleft()\n        if cost[r][c][k] != -1:\n            continue\n        cost[r][c][k] = step\n        for dr, dc in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n            nr, nc = dr + r, dc + c\n            # check boundary\n            if grid[nr][nc] == 1:\n                if k == max_k:\n                    conitnue\n                if cost[nr][nc][k + 1] == -1:\n                    cost[nr][nc][k + 1] = step + 1\n                    q.append((nr, nc, k + 1, step + 1))\n            else:\n                if cost[nr][nc][k] == -1:\n                    cost[nr][nc][k] = step + 1\n                    q.append((nr, nc, k, step + 1))\n                \n    return min(cost[row - 1][col - 1])\n    \n\\\"\\\"\\\"\n\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], max_k: int) -> int:\n        row = len(grid)\n        if not row:\n            return -1\n        col = len(grid[0])\n        if not col:\n            return -1\n        \n        MAX_STEP = row * col + 1\n        \n        visited_min_removal = [[MAX_STEP for _ in range(col)] for _ in range(row)]\n        cost = [[[MAX_STEP for _ in range(max_k + 1)] for _ in range(col)] for _ in range(row)]\n        visited_min_removal[0][0] = 0\n        cost[0][0][0] = 0\n\n        q = deque()\n        q.append((0, 0, 0, 0)) # row, col, number removed obstacle, step\n        while q:\n            r, c, k, step  = q.popleft()\n            for dr, dc in [(1, 0), (-1, 0), (0, 1), (0, -1)]:\n                nr, nc = dr + r, dc + c\n                if not (0 <= nr < row and 0 <= nc < col):\n                    continue\n                if grid[nr][nc] == 1:\n                    if k == max_k:\n                        continue\n                    if visited_min_removal[nr][nc] > k + 1:\n                        cost[nr][nc][k + 1] = step + 1\n                        visited_min_removal[nr][nc] = k + 1\n                        q.append((nr, nc, k + 1, step + 1))\n                else:\n                    if cost[nr][nc][k] == MAX_STEP:\n                        cost[nr][nc][k] = step + 1\n                        visited_min_removal[nr][nc] = k\n                        q.append((nr, nc, k, step + 1))\n\n        ans = min(cost[row - 1][col - 1])\n        if ans == MAX_STEP:\n            return -1\n        else:\n            return ans", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        nodes = deque()\n        visited = {}\n        nodes.append([(0, 0), k, 0])\n        ans = []\n        while nodes:\n            x, r, steps = nodes.popleft()\n            if x[0] == len(grid)-1 and x[1] == len(grid[0])-1:\n                ans.append(steps)\n                break\n            if x in visited and visited[x] >= r:\n                continue\n            visited[x] = r\n            if x[0]>0 and r-grid[x[0]-1][x[1]]>-1:\n                nodes.append([(x[0]-1, x[1]), r-grid[x[0]-1][x[1]], steps+1])\n            if x[0] < len(grid)-1 and r-grid[x[0]+1][x[1]]>-1:\n                nodes.append([(x[0]+1, x[1]), r-grid[x[0]+1][x[1]], steps+1])\n            if x[1] > 0 and r-grid[x[0]][x[1]-1]>-1:\n                nodes.append([(x[0], x[1]-1), r-grid[x[0]][x[1]-1], steps+1])\n            if x[1] < len(grid[0])-1 and r-grid[x[0]][x[1]+1]>-1:\n                nodes.append([(x[0], x[1]+1), r-grid[x[0]][x[1]+1], steps+1])\n\n        if not ans:\n            return -1\n        return min(ans)\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]\n        cost = 0\n        this_layer, next_layer = 1, 0\n        reached = False\n\n        # rows = len(grid)\n        # cols = len(grid[0]) if rows else 0\n        visited = [[-1] * len(grid[0]) for _ in range(len(grid))]\n        visited[0][0] = k\n        q = deque([(0, 0, k)])\n        while q:\n            r, c, p = q.popleft()\n            if r == len(grid)-1 and c == len(grid[0])-1 and grid[r][c] != 1:\n                reached = True\n                break\n            for i in range(4):\n                x, y = c + dx[i], r + dy[i]\n                if x < 0 or x >= len(grid[0]) or y < 0 or y >= len(grid):\n                    continue\n                k = p - grid[y][x]\n                if p <= visited[y][x]: # have visited here on a better path.\n                    continue\n                q.append((y, x, k))\n                visited[y][x] = k\n                next_layer += 1\n            this_layer -= 1\n            if this_layer == 0:\n                this_layer = next_layer\n                next_layer = 0\n                cost += 1\n                \n        if not reached:\n            return -1\n        return cost", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        rows, cols = len(grid), len(grid[0])\n        if rows == 1 and cols == 1:\n            return 0\n\n        # queue = deque([(0,0,k,0)])\n        # visited = set([(0,0,k)])\n\n        if k > (rows-1 + cols-1):\n            return rows-1 + cols-1\n        \n        queue = deque([(0,0,k)])\n        visited = set([(0,0,k)])\n        steps = 0\n        while queue:\n            nxt = []\n            # for r, c, eliminate, steps in queue:\n            for r, c, eliminate in queue:\n                for nr, nc in [(r-1, c), (r, c+1), (r+1, c), (r, c-1)]:\n                    if nr >= 0 and nr < rows and nc >= 0 and nc < cols:\n                        if grid[nr][nc] == 1 and eliminate > 0 and (nr, nc, eliminate-1) not in visited:\n                            visited.add((nr, nc, eliminate-1))\n                            nxt.append((nr, nc, eliminate-1))#, steps+1))\n                        if grid[nr][nc] == 0 and (nr, nc, eliminate) not in visited:\n                            if nr == rows-1 and nc == cols-1:\n                                return steps+1\n                            visited.add((nr, nc, eliminate))\n                            nxt.append((nr, nc, eliminate))#, steps+1))\n            queue = nxt\n            steps += 1\n\n        return -1\n\n#         while queue:\n#             r, c, eliminate, steps = queue.popleft()\n#             for nr, nc in [(r-1, c), (r, c+1), (r+1, c), (r, c-1)]:\n#                 if nr >= 0 and nr < rows and nc >= 0 and nc < cols:\n#                     if grid[nr][nc] == 1 and eliminate > 0 and (nr, nc, eliminate-1) not in visited:\n#                         visited.add((nr, nc, eliminate-1))\n#                         queue.append((nr, nc, eliminate-1, steps+1))\n#                     if grid[nr][nc] == 0 and (nr, nc, eliminate) not in visited:\n#                         if nr == rows-1 and nc == cols-1:\n#                             return steps+1\n#                         visited.add((nr, nc, eliminate))\n#                         queue.append((nr, nc, eliminate, steps+1))\n\n#         return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: return -1\n        m, n = len(grid), len(grid[0])\n        if grid[0][0] != 0: return -1\n        if m == 1 and n == 1: return 0 # no need to walk\n        di = [(-1, 0), (1, 0), (0, -1), (0, 1)]\n        def get_nei(i, j): \n            return [(i+x, j+y) for (x, y) in di if 0<=i+x<=m-1 and 0<=j+y<=n-1]\n        \n        seen = {(0, 0): 0}\n        seen2 = {(0, 0): k}\n        q = collections.deque()\n        q.append((0, 0, k, 0))\n        while q: \n            i, j, ob, depth = q.popleft()\n            for x, y in get_nei(i, j): \n                cob = ob\n                if x == m-1 and y == n-1 and cob >= 0: \n                    return depth+1\n                if grid[x][y] == 1: \n                    cob -= 1\n                    if cob < 0: \n                        continue\n                if (x, y) in seen and seen[(x, y)] <= depth+1 and seen2[(x, y)] >= cob: \n                    continue\n                seen[(x, y)] = depth+1\n                seen2[(x, y)] = cob\n                q.append((x, y, cob, depth+1))\n        return -1\n        \n    \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if len(grid) == 1 and len(grid[0]) == 1:\n            return 0 if k >= grid[0][0] else -1\n        nextIterations = [(0,0,k)]\n        visited = {}\n        count = 0\n        while len(nextIterations) > 0:\n            newNextIteration = []\n            for it in nextIterations:\n                directions =[[0,1],[0,-1],[1, 0],[-1, 0]]\n                for dir in directions:\n                    newRow = it[0] + dir[0]\n                    newCol = it[1] + dir[1]\n                    if newRow >=0 and newCol >=0 and newRow < len(grid) and newCol < len(grid[0]):\n                        if newRow == len(grid) -1 and newCol == len(grid[0]) - 1:\n                            if grid[newRow][newCol] == 0 or it[2] > 0:\n                                return count + 1\n                        if it[2] - grid[newRow][newCol] >= 0:\n                            if (newRow, newCol) not in visited or visited[(newRow, newCol)] < it[2] - grid[newRow][newCol]:\n                                newNextIteration.append((newRow, newCol, it[2] - grid[newRow][newCol]))\n                                visited[(newRow, newCol)] = it[2] - grid[newRow][newCol]\n            count += 1\n            nextIterations = newNextIteration\n                        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        queue = deque()\n        visited = {}\n        queue.append((0, 0, 0, 0))\n        while queue:\n            x, y, eliminated, count = queue.popleft()\n            if x == len(grid) - 1 and y == len(grid[0]) - 1:\n                return count\n            if (x, y) in visited and eliminated >= visited[x, y]:\n                continue\n            visited[x, y] = eliminated\n            for i, j in ((0, 1), (1, 0), (0, -1), (-1, 0)):\n                nx, ny = x + i, y + j\n                if 0 <= nx < len(grid) and 0 <= ny < len(grid[0]) and eliminated + grid[nx][ny] <= k:\n                    queue.append((nx, ny, eliminated + grid[nx][ny], count + 1))\n        return -1\n            \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid:\n            return -1\n        \n        queue = collections.deque([(0, 0, 0)])\n        visited = collections.defaultdict(int)\n        visited[(0, 0)] = 0\n        dist = 0\n        \n        while queue:\n            for _ in range(len(queue)):\n                x, y, o = queue.popleft()\n                #print(x, y, o)\n                if o > k:\n                    continue\n                elif (x, y) == (len(grid) - 1, len(grid[0]) - 1):\n                    return dist\n                else:\n                    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]\n                    for direction in directions:\n                        dx, dy = direction\n                        if x + dx < 0 or x + dx >= len(grid) or y + dy < 0 or y + dy >= len(grid[0]):\n                            continue\n                        if grid[x+dx][y+dy] == 1:\n                            if o + 1 > k or (x + dx, y + dy) in visited and o + 1 >= visited[(x + dx, y + dy)]:\n                                continue\n                            else:\n                                queue.append((x + dx, y + dy, o + 1))\n                                visited[(x+dx, y+dy)] = o + 1\n                        else:\n                            if o > k or (x + dx, y + dy) in visited and o >= visited[(x + dx, y + dy)]:\n                                continue\n                            else:\n                                queue.append((x + dx, y + dy, o))\n                                visited[(x+dx, y+dy)] = o\n            dist += 1\n        \n        return -1\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # i,j,k\n        # memo = {}\n        \n        H=len(grid)\n        W=len(grid[0])\n        direction = [[0,1],[0,-1],[1,0],[-1,0]]\n        \n        def possible(i,j):\n            res = []\n            for add in direction:\n                i_, j_ = i+add[0], j+add[1]\n                if 0<=i_ and i_<H and 0<=j_ and j_<W:\n                    res.append([i_, j_])\n                    \n            return res\n        \n        queue = [(0,0,k)]\n        step = 0\n        q = 0\n        K = k\n        \n        # i,j,k\n        visited = {}\n        visited[(0,0)] = k\n        \n        ## \u603b\u662f\u8981\u68c0\u67e5\uff080\uff0c0\uff09\u7684case!\n        if (0,0) == (H-1,W-1):\n            return step\n        \n        while len(queue) > q:\n            step+=1\n            size = len(queue)-q\n            for _ in range(size):\n                i,j,k = queue[q]\n                q+=1\n                \n                for i_,j_ in possible(i,j):\n                    if grid[i_][j_] == 0:\n                        if (i_,j_) not in visited or visited[(i_,j_)]<k:\n                            queue.append((i_,j_,k))\n                            visited[(i_,j_)]=k\n                            if i_ == H-1 and j_ == W-1:\n                                return step\n                    else:\n                        if k-1>=0:\n                            if (i_,j_) not in visited or visited[(i_,j_)]<k-1:\n                                queue.append((i_,j_,k-1))\n                                visited[(i_,j_)]=k-1\n                                if i_ == H-1 and j_ == W-1:\n                                    return step\n                                \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        N, M = len(grid), len(grid[0])\n        moves = [(-1,0),(1,0),(0,-1),(0,1)]\n        \n        queue = [(-1, 0, N-1,M-1,k)]\n        visited = set([(N-1,M-1,k)])\n        while queue:\n            p, m, i, j, k = heapq.heappop(queue)\n            if i == 0 and j == 0:\n                return m\n            \n            for move in moves:\n                ni, nj = i+move[0], j+move[1]\n                if N > ni >= 0 <= nj < M:\n                    nk = k-grid[ni][nj]\n                    if nk >= 0 and (ni, nj, nk) not in visited:\n                        #print(ni, nj, nk, m-1)\n                        visited.add((ni,nj,nk))\n                        heapq.heappush(queue, (ni+nj+m+1,m+1,ni,nj,nk))\n        return -1", "from collections import deque\nclass Solution:\n    \n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        num_rows = len(grid)   \n        num_cols = len(grid[0])\n        \n        frontier = deque([(0, 0, 0, k)]) # frontier keeps (row, col, dist, k)\n        visited = {}\n        \n        while frontier:\n                row, col, dist, chances = frontier.popleft()\n                if chances < 0:\n                    continue\n                if row == num_rows - 1 and col == num_cols - 1:\n                    return dist\n                \n                #get neighbours\n                neighbours = [(row - 1, col), (row + 1, col), (row, col - 1), (row, col + 1)]\n                \n                for neighbour in neighbours:\n                    if self.valid_neighbour(neighbour, grid):\n                        neigh_row = neighbour[0]\n                        neigh_col = neighbour[1]\n                        if neighbour not in visited:\n                            if grid[neigh_row][neigh_col] == 0:\n                                frontier.append((neigh_row, neigh_col, dist + 1, chances))\n                                visited[neighbour] = (dist + 1, chances)\n                            else:\n                                frontier.append((neigh_row, neigh_col, dist + 1, chances - 1))\n                                visited[neighbour] = (dist + 1, chances - 1)\n                        else: # if visited, only visit again if chance is larger\n                            last_dist, last_chance = visited[neighbour]\n                            if last_chance < chances:\n                                if grid[neigh_row][neigh_col] == 0:\n                                    frontier.append((neigh_row, neigh_col, dist + 1, chances))\n                                    visited[neighbour] = (dist + 1, chances)\n                                else:\n                                    frontier.append((neigh_row, neigh_col, dist + 1, chances - 1))\n                                    visited[neighbour] = (dist + 1, chances - 1)\n                                \n                            \n        return -1\n    \n    def valid_neighbour(self, neighbour, grid):\n        row = neighbour[0]\n        col = neighbour[1]\n        \n        if row < 0 or row >= len(grid) or col < 0 or col >= len(grid[row]):\n            return False\n        return True\n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        q = collections.deque([[0, 0, 0]])    # row, col, num of obstables met so far\n        visited = {(0, 0): 0}                 # row, col   =>   num of obstables met so far\n        steps = 0\n        \n        while q:\n            size = len(q)\n            for x in range(size):\n                r, c, obs = q.popleft()\n                if obs > k: \n                    continue\n                if r == m - 1 and c == n - 1: \n                    return steps\n                for r2, c2 in [[r+1, c], [r-1, c], [r, c+1], [r, c-1]]:\n                    if 0 <= r2 < m and 0 <= c2 < n:\n                        next_obs = obs \n                        if grid[r2][c2] == 1:\n                            next_obs += 1\n                        if next_obs < visited.get((r2, c2), float('inf')):\n                            visited[(r2, c2)] = next_obs\n                            q.append([r2, c2, next_obs])\n            steps += 1       \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # algorithm: bfs with a twist\n        # each node in graph is (r, c, num_already_eliminate)\n        # think of num_already_eliminate is the \\\"capacity\\\"\n        # already used so far\n        \n        rows, cols = len(grid), len(grid[0])\n        if rows == 1 and cols == 1:\n            return 0\n\n        if k > (rows-1 + cols-1):\n            return rows-1 + cols-1\n        \n        queue = deque([(0,0,k)])\n        visited = set([(0,0,k)])\n        steps = 0\n        while queue:\n            nxt = []\n            for r, c, eliminate in queue:\n                for nr, nc in [(r-1, c), (r, c+1), (r+1, c), (r, c-1)]:\n                    if nr >= 0 and nr < rows and nc >= 0 and nc < cols:\n                        if grid[nr][nc] == 1 and eliminate > 0 and (nr, nc, eliminate-1) not in visited:\n                            visited.add((nr, nc, eliminate-1))\n                            nxt.append((nr, nc, eliminate-1))\n                        if grid[nr][nc] == 0 and (nr, nc, eliminate) not in visited:\n                            if nr == rows-1 and nc == cols-1:\n                                return steps+1\n                            visited.add((nr, nc, eliminate))\n                            nxt.append((nr, nc, eliminate))\n            queue = nxt\n            steps += 1\n\n        return -1", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        last_blast = collections.defaultdict(lambda: 0)\n        visited = set()\n        def getN(i, j):\n            direction = [[0,1],[1,0],[-1,0],[0,-1]]\n            for diff in direction:\n                i_diff, j_diff = diff\n                curr_i = i+i_diff\n                curr_j = j+j_diff\n                if curr_i < 0 or curr_j < 0 or curr_i >= len(grid) or curr_j >= len(grid[0]):\n                    continue\n                yield [curr_i, curr_j]\n        \n        node_to_trav = deque()\n        node_to_trav.append((0,0,k))\n        \n        min_steps = -1\n        \n        while node_to_trav:\n            trav_length = len(node_to_trav)\n            min_steps += 1\n            for i in range(trav_length):\n                curr_node = node_to_trav.popleft()\n                i, j, r_dyno = curr_node\n                visited.add((i, j))\n                if i == len(grid) - 1 and j == len(grid[0]) - 1:\n                    return min_steps\n                for n in getN(i,j):\n                    n_i, n_j = n\n                    \n                    if grid[n_i][n_j] == 0:\n                        if (n_i, n_j, r_dyno) not in visited:\n                            node_to_trav.append((n_i, n_j, r_dyno))\n                            visited.add((n_i, n_j, r_dyno))\n                    elif r_dyno > last_blast[(n_i, n_j)]:\n                        if (n_i, n_j, r_dyno-1) not in visited:\n                            node_to_trav.append((n_i, n_j, r_dyno-1))\n                            last_blast[(n_i,n_j)] = r_dyno-1\n                            visited.add((n_i, n_j, r_dyno-1))\n                            \n        return -1\n    \n    \n", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        last_blast = collections.defaultdict(lambda: 0)\n        visited = set()\n        def getN(i, j):\n            direction = [[0,1],[1,0],[-1,0],[0,-1]]\n            for diff in direction:\n                i_diff, j_diff = diff\n                curr_i = i+i_diff\n                curr_j = j+j_diff\n                if curr_i < 0 or curr_j < 0 or curr_i >= len(grid) or curr_j >= len(grid[0]):\n                    continue\n                yield [curr_i, curr_j]\n        \n        node_to_trav = deque()\n        node_to_trav.append((0,0,k))\n        \n        min_steps = -1\n        \n        while node_to_trav:\n            trav_length = len(node_to_trav)\n            min_steps += 1\n            for i in range(trav_length):\n                curr_node = node_to_trav.popleft()\n                i, j, r_dyno = curr_node\n                visited.add((i, j))\n                if i == len(grid) - 1 and j == len(grid[0]) - 1:\n                    return min_steps\n                for n in getN(i,j):\n                    n_i, n_j = n\n                    \n                    if grid[n_i][n_j] == 0:\n                        if (n_i, n_j, r_dyno) not in visited:\n                            node_to_trav.append((n_i, n_j, r_dyno))\n                            visited.add((n_i, n_j, r_dyno))\n                    elif r_dyno > last_blast[(n_i, n_j)]:\n                        if (n_i, n_j, r_dyno-1) not in visited:\n                            node_to_trav.append((n_i, n_j, r_dyno-1))\n                            last_blast[(n_i,n_j)] = r_dyno-1\n                            visited.add((n_i, n_j, r_dyno-1))\n        return -1\n    \n    \n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def valid(i,j):\n            if i>=0 and j>=0 and i<len(grid) and j<len(grid[0]):\n                return True\n            return False\n        \n        dq=deque([(0,0,k,0)])\n        visited={}\n        res=math.inf\n        \n        def search(i,j,k,l):\n            if (i,j) in visited and visited[(i,j)]>=k:\n                return False\n            visited[(i,j)]=k if (i,j) not in visited else max(k,visited[(i,j)])\n            nonlocal res\n            if k<0:\n                return False\n            if i==len(grid)-1 and j==len(grid[0])-1:\n                res=l\n                return True\n            for di,dj in [(1,0),(0,1),(-1,0),(0,-1)]:\n                if valid(i+di,j+dj):\n                    next_k=k if grid[i+di][j+dj]==0 else k-1\n                    dq.append((i+di,j+dj,next_k,l+1))\n            \n            return False\n        while dq:\n            i,j,k,l=dq.popleft()\n            if search(i,j,k,l):\n                break\n        return res if res!=math.inf else -1", "import collections\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        last_blast = collections.defaultdict(lambda: 0)\n        visited = set()\n        def getN(i, j):\n            direction = [[0,1],[1,0],[-1,0],[0,-1]]\n            for diff in direction:\n                i_diff, j_diff = diff\n                curr_i = i+i_diff\n                curr_j = j+j_diff\n                if curr_i < 0 or curr_j < 0 or curr_i >= len(grid) or curr_j >= len(grid[0]):\n                    continue\n                yield [curr_i, curr_j]\n        \n        node_to_trav = deque()\n        node_to_trav.append((0,0,k))\n        \n        min_steps = -1\n        \n        while node_to_trav:\n            trav_length = len(node_to_trav)\n            min_steps += 1\n            for i in range(trav_length):\n                curr_node = node_to_trav.popleft()\n                i, j, r_dyno = curr_node\n                visited.add((i, j))\n                if i == len(grid) - 1 and j == len(grid[0]) - 1:\n                    return min_steps\n                for n in getN(i,j):\n                    n_i, n_j = n\n                    if grid[n_i][n_j] == 0:\n                        if (n_i, n_j, r_dyno) not in visited:\n                            node_to_trav.append((n_i, n_j, r_dyno))\n                            visited.add((n_i, n_j, r_dyno))\n                    elif r_dyno > last_blast[(n_i, n_j)]:\n                        if (n_i, n_j, r_dyno-1) not in visited:\n                            node_to_trav.append((n_i, n_j, r_dyno-1))\n                            last_blast[(n_i,n_j)] = r_dyno-1\n                            visited.add((n_i, n_j, r_dyno-1))\n                        \n        return -1\n    \n    \n", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def valid(i,j):\n            if i>=0 and j>=0 and i<len(grid) and j<len(grid[0]):\n                return True\n            return False\n        \n        dq=deque([(0,0,k,0)])\n        visited={}\n        res=math.inf\n        \n        def search(i,j,k,l):\n            if (i,j) in visited and visited[(i,j)]>=k:\n                return False\n            visited[(i,j)]=k if (i,j) not in visited else max(k,visited[(i,j)])\n            nonlocal res\n            \n            if k<0:\n                return False\n            if i==len(grid)-1 and j==len(grid[0])-1:\n                res=l\n                return True\n            # shortcut(\u53ea\u6709(i,j) not in visited\u624d\u80fd\u4fdd\u8bc1\u524d\u9762\u4e5f\u662f\u6700\u77ed\u8def\u5f84)\n            if len(grid)-1-i+len(grid[0])-1-j<=k+1 and (i,j) not in visited:\n                res=l+len(grid)-1-i+len(grid[0])-1-j\n                return True\n            for di,dj in [(1,0),(0,1),(-1,0),(0,-1)]:\n                if valid(i+di,j+dj):\n                    next_k=k if grid[i+di][j+dj]==0 else k-1\n                    dq.append((i+di,j+dj,next_k,l+1))\n            \n            return False\n        while dq:\n            i,j,k,l=dq.popleft()\n            if search(i,j,k,l):\n                break\n        return res if res!=math.inf else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        dp = defaultdict(lambda :float('inf'))\n        dp[(m-1,n-1,k)]=0\n        todo = [(m-1,n-1,k)]\n        seen = {(m-1,n-1):k}\n        while todo:\n            new = []\n            for i,j,r in todo:\n                if (i,j)==(0,0):return dp[(i,j,r)]\n                for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                    if  0<=x<m and 0<=y<n and(grid[x][y] == 0 or r>0):\n                        \n                        new_r = r if grid[x][y] == 0 else r-1\n                        \n                        dp[(x,y,new_r)] = min(dp[(x,y,new_r)], dp[(i,j,r)]+1)\n                        \n                        if (x,y) not in seen or seen[(x,y)]<new_r:\n                            \n                            new.append((x,y,new_r))\n                            seen[(x,y)] = new_r\n                    \n                            \n            todo = new\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]\n        this_layer, next_layer = 1, 0\n        reached = False\n        cost = 0\n\n        visited = [[-1] * len(grid[0]) for _ in range(len(grid))]\n        visited[0][0] = k\n        q = deque([(0, 0, k)])\n        while q:\n            r, c, p = q.popleft()\n            if r == len(grid)-1 and c == len(grid[0])-1 and grid[r][c] != 1:\n                reached = True\n                break\n            for i in range(4):\n                x, y = c + dx[i], r + dy[i]\n                if x < 0 or x >= len(grid[0]) or y < 0 or y >= len(grid):\n                    continue\n                if p-grid[y][x] <= visited[y][x]: # have visited here on a better path.\n                    continue\n                q.append((y, x, p - grid[y][x]))\n                visited[y][x] = p - grid[y][x]\n                next_layer += 1\n            this_layer -= 1\n            if this_layer == 0:\n                this_layer = next_layer\n                next_layer = 0\n                cost += 1\n                \n        if not reached:\n            return -1\n        return cost", "class Solution:\n    # O(m x n) time, O(m x n) space\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        DELTAS = [(0, 1), (0, -1), (1, 0), (-1, 0)]\n        EMPTY = 0\n        m, n = len(grid), len(grid[0])\n        q = deque([(0, 0, 0, 0)])\n        seen = defaultdict(lambda: float(\\\"inf\\\"))\n        seen[0, 0] = 0\n        \n        def is_valid(i, j, removal):\n            return 0 <= i < m and 0 <= j < n and removal < seen[i, j]\n        \n        while q:\n            i, j, step, removal = q.popleft()\n            if i == m - 1 and j == n - 1:\n                return step\n            for di, dj in DELTAS:\n                i1, j1 = i + di, j + dj\n                if is_valid(i1, j1, removal):\n                    if grid[i1][j1] == EMPTY:\n                        seen[i1, j1] = removal\n                        q.append((i1, j1, step + 1, removal))\n                    elif removal < k:  # Not empty but still removable\n                        seen[i1, j1] = removal + 1\n                        q.append((i1, j1, step + 1, removal + 1))\n        \n        return -1\n                        \n            ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        R,C = len(grid),len(grid[0])\n        if R == 1 and C == 1:\n            return 0\n        if k >= R-1 + C-1:\n            return R-1 + C-1\n        \n        q = collections.deque([(0,0,k,0)])\n        seen = set([(0,0,k)])        \n        while q:\n            i,j,left,steps = q.popleft()\n            for new_i,new_j in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                if 0 <= new_i < R and 0 <= new_j < C:\n                    if grid[new_i][new_j] == 1 and left > 0 and (new_i,new_j,left-1) not in seen:\n                        seen.add((new_i,new_j,left-1))\n                        q.append((new_i,new_j,left-1,steps+1))\n                    elif grid[new_i][new_j] == 0 and (new_i,new_j,left) not in seen:\n                        if new_i == R-1 and new_j == C-1:\n                            return steps + 1\n                        seen.add((new_i,new_j,left))\n                        q.append((new_i,new_j,left,steps+1))\n        return -1", "class Solution:\n    # O(m x n) time, O(m x n) space\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        DELTAS = [(0, 1), (0, -1), (1, 0), (-1, 0)]\n        EMPTY = 0\n        m, n = len(grid), len(grid[0])\n        q = deque([(0, 0, 0, 0)])\n        seen = defaultdict(lambda: float(\\\"inf\\\"))\n        seen[0, 0] = 0\n        \n        def is_valid(i, j):\n            return 0 <= i < m and 0 <= j < n\n        \n        while q:\n            i, j, step, removal = q.popleft()\n            if i == m - 1 and j == n - 1:\n                return step\n            for di, dj in DELTAS:\n                i1, j1 = i + di, j + dj\n                if is_valid(i1, j1):\n                    if grid[i1][j1] == EMPTY and removal < seen[i1, j1]:\n                        seen[i1, j1] = removal\n                        q.append((i1, j1, step + 1, removal))\n                    elif removal < k and removal + 1 < seen[i1, j1]:  # Not empty but still removable\n                        seen[i1, j1] = removal + 1\n                        q.append((i1, j1, step + 1, removal + 1))\n        \n        return -1\n                        \n            ", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m = len(grid)\n        n = len(grid[0])\n        dp = defaultdict(lambda :float('inf'))\n        dp[(m-1,n-1,k)]=0\n        todo = [(m-1,n-1,k)]\n        seen = {(m-1,n-1):k}\n        while todo:\n            new = []\n            for i,j,r in todo:\n                for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:\n                    if  0<=x<m and 0<=y<n and(grid[x][y] == 0 or r>0):\n                        new_r = r if grid[x][y] == 0 else r-1\n                        dp[(x,y,new_r)] = min(dp[(x,y,new_r)], dp[(i,j,r)]+1)\n                        if (x,y) not in seen or seen[(x,y)]<new_r:\n                            new.append((x,y,new_r))\n                            seen[(x,y)] = new_r\n                    \n                            \n            todo = new\n        #print(dp)\n        ans = min(dp[(0,0,i)] for i in range(k+1))\n        return ans if ans<float('inf') else -1", "from collections import deque\nclass Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        def valid(i,j):\n            if i>=0 and j>=0 and i<len(grid) and j<len(grid[0]):\n                return True\n            return False\n        \n        dq=deque([(0,0,k,0)])\n        visited={}\n        res=math.inf\n        \n        def search(i,j,k,l):\n            nonlocal res\n            if l>=res:\n                return False\n            if (i,j) in visited and visited[(i,j)]>=k:\n                return False\n            visited[(i,j)]=k if (i,j) not in visited else max(k,visited[(i,j)])\n            \n            if k<0:\n                return False\n            if i==len(grid)-1 and j==len(grid[0])-1:\n                res=l\n                return True\n            # shortcut(\u53ea\u6709(i,j) not in visited\u624d\u80fd\u4fdd\u8bc1\u524d\u9762\u4e5f\u662f\u6700\u77ed\u8def\u5f84)\n            if len(grid)-1-i+len(grid[0])-1-j<=k+1:\n                res=min(res,l+len(grid)-1-i+len(grid[0])-1-j)\n                if (i,j) not in visited:\n                    return True\n            for di,dj in [(1,0),(0,1),(-1,0),(0,-1)]:\n                if valid(i+di,j+dj):\n                    next_k=k if grid[i+di][j+dj]==0 else k-1\n                    dq.append((i+di,j+dj,next_k,l+1))\n            \n            return False\n        while dq:\n            i,j,k,l=dq.popleft()\n            if search(i,j,k,l):\n                break\n        return res if res!=math.inf else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: return -1\n        m, n = len(grid), len(grid[0])\n        if grid[0][0] != 0: return -1\n        if m == 1 and n == 1: return 0 # no need to walk\n        di = [(-1, 0), (1, 0), (0, -1), (0, 1)]\n        def get_nei(i, j): \n            return [(i+x, j+y) for (x, y) in di if 0<=i+x<=m-1 and 0<=j+y<=n-1]\n        \n        seen = {(0, 0): 0}\n        seen2 = {(0, 0): k}\n        q = collections.deque()\n        q.append((0, 0, k, 0))\n        while q: \n            i, j, ob, depth = q.popleft()\n            for x, y in get_nei(i, j): \n                cob = ob\n                if x == m-1 and y == n-1 and ob >= 0: \n                    return depth+1\n                if grid[x][y] == 1: \n                    cob -= 1\n                    if cob < 0: \n                        continue\n                if (x, y) in seen and seen[(x, y)] <= depth+1 and seen2[(x, y)] >= ob: \n                    continue\n                seen[(x, y)] = depth+1\n                seen2[(x, y)] = cob\n                q.append((x, y, cob, depth+1))\n        return -1\n        \n    \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        nodes = deque()\n        visited = {}\n        print((len(grid), len(grid[0])))\n        nodes.append([(0, 0), k, 0])\n        ans = []\n        while nodes:\n            x, r, steps = nodes.popleft()\n            # print([x, r, steps], end=' ')\n            if x[0] == len(grid)-1 and x[1] == len(grid[0])-1:\n                ans.append(steps)\n                break\n            if x in visited and visited[x] >= r:\n                continue\n            visited[x] = r\n            if x[0]>0 and r-grid[x[0]-1][x[1]]>-1:\n                nodes.append([(x[0]-1, x[1]), r-grid[x[0]-1][x[1]], steps+1])\n            if x[0] < len(grid)-1 and r-grid[x[0]+1][x[1]]>-1:\n                nodes.append([(x[0]+1, x[1]), r-grid[x[0]+1][x[1]], steps+1])\n            if x[1] > 0 and r-grid[x[0]][x[1]-1]>-1:\n                nodes.append([(x[0], x[1]-1), r-grid[x[0]][x[1]-1], steps+1])\n            if x[1] < len(grid[0])-1 and r-grid[x[0]][x[1]+1]>-1:\n                nodes.append([(x[0], x[1]+1), r-grid[x[0]][x[1]+1], steps+1])\n        \n        print(ans)\n        if not ans:\n            return -1\n        return min(ans)\n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if not grid: return -1\n        m, n = len(grid), len(grid[0])\n        if grid[0][0] != 0: return -1\n        if m == 1 and n == 1: return 0 # no need to walk\n        di = [(-1, 0), (1, 0), (0, -1), (0, 1)]\n        def get_nei(i, j): \n            return [(i+x, j+y) for (x, y) in di if 0<=i+x<=m-1 and 0<=j+y<=n-1]\n        \n        seen = {(0, 0): 0}\n        seen2 = {(0, 0): k}\n        q = collections.deque()\n        q.append((0, 0, k, 0))\n        while q: \n            i, j, ob, depth = q.popleft()\n            for x, y in get_nei(i, j): \n                cob = ob\n                if x == m-1 and y == n-1 and ob >= 0: \n                    return depth+1\n                \n                if grid[x][y] == 1: \n                    cob -= 1\n                    if cob < 0: \n                        continue\n                if (x, y) in seen and seen[(x, y)] <= depth+1 and seen2[(x, y)] >= ob: \n                    continue\n                seen[(x, y)] = depth+1\n                seen2[(x, y)] = cob\n                q.append((x, y, cob, depth+1))\n        print(seen)\n        print(seen2)\n        return -1\n        \n    \n        \n        \n", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        \n        # i,j,k\n        # memo = {}\n        \n        H=len(grid)\n        W=len(grid[0])\n        direction = [[0,1],[0,-1],[1,0],[-1,0]]\n        \n        def possible(i,j):\n            res = []\n            for add in direction:\n                i_, j_ = i+add[0], j+add[1]\n                if 0<=i_ and i_<H and 0<=j_ and j_<W:\n                    res.append([i_, j_])\n                    \n            return res\n        \n        queue = [(0,0,k)]\n        step = 0\n        q = 0\n        K = k\n        \n        # i,j,k\n        visited = {}\n        visited[(0,0)] = k\n        \n        if (0,0) == (H-1,W-1):\n            return step\n        \n        while len(queue) > q:\n            step+=1\n            size = len(queue)-q\n            for _ in range(size):\n                i,j,k = queue[q]\n                q+=1\n                \n                for i_,j_ in possible(i,j):\n                    if grid[i_][j_] == 0:\n                        if (i_,j_) not in visited or visited[(i_,j_)]<k:\n                            queue.append((i_,j_,k))\n                            visited[(i_,j_)]=k\n                            if i_ == H-1 and j_ == W-1:\n                                return step\n                    else:\n                        if k-1>=0:\n                            if (i_,j_) not in visited or visited[(i_,j_)]<k-1:\n                                queue.append((i_,j_,k-1))\n                                visited[(i_,j_)]=k-1\n                                if i_ == H-1 and j_ == W-1:\n                                    return step\n                                \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        MAX_DIST = m * n\n        \n        shortest = MAX_DIST\n        visited = set([])\n        visited.add((m-1, n-1, k, 0))\n        \n        def dfs(i, j, k, steps):\n            nonlocal shortest\n            \n            if (i, j) == (0, 0):\n                shortest = min(shortest, steps)\n                return\n            \n            if grid[i][j] == 1:\n                k -= 1 \n                if k < 0:\n                    return\n            \n            if grid[i][j] == 2:\n                return\n            \n            if shortest <= steps + i + j:\n                return\n        \n            grid[i][j], save = 2, grid[i][j]\n            for x, y in (i-1, j), (i, j-1), (i+1, j), (i, j+1):\n                if m > x >= 0 <= y < n and (x, y, k, steps+1) not in visited:\n                    visited.add((x, y, k, steps+1))\n                    dfs(x, y, k, steps+1)\n                    \n            \n            grid[i][j] = save\n        \n        dfs(m-1, n-1, k, 0)\n        \n        return shortest if shortest != MAX_DIST else -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        if 0 == len(grid) - 1 and 0 == len(grid[0]) - 1:\n            return 0\n        \n        m, n = len(grid), len(grid[0])\n        seen = set()\n        q = collections.deque()\n        q.append((0, 0, k))\n        seen.add((0, 0, k))\n        steps = 0\n        direction = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        \n        while q:\n            for i in range(len(q)):\n                r, c, k = q.popleft()\n\n                for x, y in direction:\n                    R = r + x\n                    C = c + y\n                    \n                    # We are approaching a already visited cell with same k\n                    if (R, C, k) in seen:\n                        continue\n                        \n                    if R >= 0 and R < m and C >= 0 and C < n:\n                        if k > 0 and grid[R][C] == 1 and (R, C, k - 1) not in seen:\n                            q.append((R, C, k - 1))\n                            seen.add((R, C, k - 1))\n\n                        if grid[R][C] == 0 and (R, C, k) not in seen:\n                            if R == m - 1 and C == n - 1:\n                                return steps + 1\n                            q.append((R, C, k))\n                            seen.add((R, C, k))\n            steps += 1\n        \n        return -1", "class Solution:\n    def shortestPath(self, grid: List[List[int]], k: int) -> int:\n        m, n = len(grid), len(grid[0])\n        seen = set()\n        q = collections.deque()\n        q.append((0, 0, k))\n        seen.add((0, 0, k))\n        steps = 0\n        direction = [(1, 0), (-1, 0), (0, 1), (0, -1)]\n        \n        if 0 == m - 1 and 0 == n - 1:\n            return 0\n        \n        while q:\n            for i in range(len(q)):\n                r, c, k = q.popleft()\n\n                for x, y in direction:\n                    R = r + x\n                    C = c + y\n                    \n                    # We are approaching a already visited cell with same k\n                    if (R, C, k) in seen:\n                        continue\n                        \n                    if R >= 0 and R < m and C >= 0 and C < n:\n                        if k > 0 and grid[R][C] == 1 and (R, C, k - 1) not in seen:\n                            q.append((R, C, k - 1))\n                            seen.add((R, C, k - 1))\n\n                        if grid[R][C] == 0 and (R, C, k) not in seen:\n                            if R == m - 1 and C == n - 1:\n                                return steps + 1\n                            q.append((R, C, k))\n                            seen.add((R, C, k))\n            steps += 1\n        \n        return -1"]