[Python手撕]網格中的最短路徑(可以有k次破牆的機會)

Duancf發表於2024-10-02
class Solution:
    def shortestPath(self, grid: List[List[int]], k: int) -> int:
        n = len(grid)
        m = len(grid[0])

        if m == n == 1:
            return 0

        direction = [[0, 1], [-1, 0], [1, 0], [0, -1]]
        visited = [[[False] * (k + 1) for _ in range(m)] for _ in range(n)]
        visited[0][0][k] = True
        queue = deque([(0, 0, k, 0)])

        while queue:
            x, y, f, s = queue.popleft()
            for d in direction:
                next_x = x + d[0]
                next_y = y + d[1]
                if next_x == n - 1 and next_y == m - 1:
                    return s + 1
                else:
                    # 判斷下一個位置是否超出範圍
                    if 0 <= next_x < n and 0 <= next_y < m:
                        # 如果下一個位置是牆,必須保證還有破牆術,
                        # 並且我們必須保證之前沒有路徑訪問過這個位置的時候剩餘的破牆數等於當前路徑剩餘的破牆術,
                        # 更不能容忍之前路徑剩餘的破牆術大於當前路徑剩餘的破牆術,
                        # 上面兩種情況下,當前路徑是不可能比之前路徑更快的
                        if (
                            grid[next_x][next_y] == 1
                            and f >= 1
                            and sum(visited[next_x][next_y][f - 1 : k + 1]) == 0
                        ):
                            visited[next_x][next_y][f - 1] = 1
                            queue.append([next_x, next_y, f - 1, s + 1])
                        elif (
                            grid[next_x][next_y] == 0
                            and sum(visited[next_x][next_y][f : k + 1]) == 0
                        ):
                            visited[next_x][next_y][f] = 1
                            queue.append([next_x, next_y, f, s + 1])
        return -1

相關文章