📌  相关文章
📜  求在恰好 k 次跳跃中到达最后一个岛所需的最小跳跃长度(1)

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

恰好k次跳跃到达最后一个岛的最小跳跃长度

在一个由岛屿和海洋组成的网格中,有一个人希望穿过所有的岛屿,通过跳跃从一个岛上到另一个岛上。 这个人每次跳跃的长度可以是1, 2或3个单位,需要恰好k次跳跃才能到达最后一个岛。所有岛屿的坐标都是整数,表示为(i, j)。你可以假设起始岛和目标岛的坐标已知。

为了使跳跃更容易,这个人可以按任意顺序访问岛屿,只要在最后一次跳跃之前访问所有岛屿即可。也就是说,在恰好跳跃k次之前,访问一遍所有岛屿并不一定非得是遍历图的某一种顺序,只需保证恰好跳跃k次之前所有岛屿都被访问即可。

求在恰好k次跳跃中到达最后一个岛建所需的最小跳跃长度。

解法

题目要求恰好跳跃k次,而不是恰好访问k个岛屿。因此,这是一个最短路问题。我们可以使用BFS来求解最短距离。

BFS是一种广度优先搜索算法。它从起始点开始,从一层到另一层遍历所有可能的位置,并记录到达每个位置的最短距离。一旦到达目标位置,算法就可以停止搜索。

在本题中,我们可以以每个岛屿为起始点运行BFS,以每个岛屿的位置和跳跃次数(k)作为状态。将所有可到达的点加入到队列中,并记录到达它们的距离。每个状态可以转移到k+1的下一个状态,直到达到最终的岛。

因为每个状态受到位置和跳跃数量的影响,所以我们可以使用三维数组来储存状态(起始岛屿位置,跳跃次数,当前位置),其中第1维表示状态的编号,第2维表示跳跃次数(k),第3维表示当前位置。

代码

以下为Python的实现代码:

from typing import List
from collections import deque

def shortestPath(mat: List[List[int]], k: int) -> int:
    m, n = len(mat), len(mat[0])
    visited = set()

    # 初始化状态
    start_pos = [(i, j) for i in range(m) for j in range(n) if mat[i][j] == 1]
    if not start_pos:
        return -1
    q = deque([(i, k, i, j) for i, j in start_pos])  # 状态为(当前岛屿位置,剩余跳跃数,当前位置)

    # BFS搜索
    step = 0
    while q:
        size = len(q)
        for _ in range(size):
            pos, left_k, cur_i, cur_j = q.popleft()

            if pos not in visited:
                visited.add(pos)  # 防止重复搜索
                
                # 判断是否到达终点
                if pos == (m-1, n-1):
                    return step
                
                # 遍历可到达的位置
                for next_i, next_j in [(cur_i+1, cur_j), (cur_i-1, cur_j), (cur_i, cur_j+1), (cur_i, cur_j-1)]:
                    if 0 <= next_i < m and 0 <= next_j < n:
                        next_pos = mat[next_i][next_j]

                        # 如果下一个位置是海洋,无法到达
                        if next_pos == 0:
                            continue

                        # 如果还可以跳跃
                        if left_k > 0:
                            q.append((pos, left_k-1, next_i, next_j))
                        else:
                            break  # 已经用完跳跃次数

        step += 1

    return -1  # 无法到达终点

以上代码包含了初始化状态,BFS搜索和回溯操作,如果执行成功,返回最小跳跃长度,如果无法到达最后一个岛,返回-1。

总结

本题可以采用BFS求解最短路径。我们可以从每个岛屿开始,并以岛屿的位置和跳跃次数作为状态。将可到达的位置添加到队列中,以跟踪每个状态的最短路径。在跳跃k次后到达终点时,我们就找到了最短路径的一条。

如果你还有疑问,请在下方评论区留言。