📌  相关文章
📜  以等于单元格值的跳跃到达目的地所需的最小单元格(1)

📅  最后修改于: 2023-12-03 15:22:04.554000             🧑  作者: Mango

以等于单元格值的跳跃到达目的地所需的最小单元格

这是一个问题,给定一个二维网格和起点、终点,每个单元格有一个数字作为该单元格的价值,你需要找到从起点到终点的最小代价路径,其中代价的定义为以等于单元格值的跳跃所需的单元格数。

思路

本题最短路求解算法的核心是 Dijkstra 算法,我们需要把单元格看作图中的节点,每个单元格都有多个可能的下一步,我们能够从当前位置跳到单元格值为当前位置加上某个数值的单元格。

我们可以用一个优先级队列,也就是小根堆,来存储待处理的单元格,我们每次pop出栈顶的单元格,如果这个单元格是终点就直接返回;否则,我们找到从当前单元格所能到达的所有单元格,并更新这些单元格的距离值和前驱信息。然后将它们加入到堆中等待处理。

以上操作会一直进行直到堆为空,这时我们就可以得到从起点到终点的最小路径代价。

代码实现

以下是 Python 语言的代码实现,其中 grid 为二维网格,(sr, sc) 为起点行列坐标,(tr, tc) 为终点行列坐标:

import heapq

def minCostPath(grid, sr, sc, tr, tc):
    m, n = len(grid), len(grid[0])
    q = [(0, sr, sc)]
    dist = {(sr, sc): 0}

    while q:
        cost, r, c = heapq.heappop(q)
        if r == tr and c == tc:
            return cost

        for i, j in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            nr, nc = r + i * grid[r][c], c + j * grid[r][c]

            if 0 <= nr < m and 0 <= nc < n:
                ncost = cost + abs(i) + abs(j)
                if ncost < dist.get((nr, nc), float('inf')):
                    dist[nr, nc] = ncost
                    heapq.heappush(q, (ncost, nr, nc))
    
    return -1 # 没有找到路径

以上代码维护了一个名为 dist 的字典来记录每个单元格的最小代价,并使用堆来存储待处理的单元格。主循环处理堆中的元素,考虑从当前单元格所能够到达的所有单元格编号之后加入到小根堆,使算法按代价从小到大选择顺序进行处理。

时间复杂度

假设二维网格的行数和列数分别为 m 和 n,我们平均需要遍历每个单元格,每次访问单元格时需要寻找它所能到达的所有单元格,但由于当前单元格价值范围在 1 到 9 之间,因此我们可以通过 4 次加、减操作从当前格子跳到它所能到达的所有下一步,即每个单元格最多能够被访问 4*9=36 次。

因此,时间复杂度为 O(mnlog(mn)),使用了大小为 O(mn) 的堆,其中在堆中插入新元素以及更新堆中元素的代价为 O(log(mn))。