小U的最大连续移动次数问题 | 豆包 MarsCode AI 刷题

114 阅读5分钟

问题重述

问题是关于在一个二维高度地图上找到最长的移动路径,其中移动需满足特定条件:只能上坡或下坡,不能在同一高度移动,且移动需交替进行(上坡后必须下坡,下坡后必须上坡)。地图的每个位置只能经过一次。目标是在给定的地图尺寸和高度分布下,计算并返回小U能够移动的最大次数,即在满足所有条件的前提下,走过的最大连续位置数量。

思路分析

小U需要在给定的m × n地图上找到最长的移动路径,该路径必须满足以下条件:

  1. 高度差异:小U只能上坡或下坡,不能在同一高度的点之间移动。
  2. 交替移动:小U的移动必须交替进行,即上坡后必须下坡,下坡后必须上坡。
  3. 唯一性:每个位置只能经过一次,不能重复行走。

为了解决这个问题,我们可以使用深度优先搜索(DFS)算法,并结合回溯来确保每个位置只被访问一次。以下是详细的思路分析:

  1. 初始化

    • 创建一个visited矩阵来跟踪哪些位置已经被访问过。
    • 初始化max_moves为0,用于记录最长的移动路径长度。
  2. 遍历起点

    • 由于小U可以从地图上的任何位置开始移动,我们需要遍历地图上的每个点作为潜在的起点。
  3. 深度优先搜索(DFS)

    • 对于每个起点,使用DFS来探索所有可能的移动路径。
    • 在DFS过程中,我们需要跟踪上一次移动是上坡还是下坡(通过last_move参数),以确保当前移动是合法的(即交替进行上坡和下坡)。
    • 对于每个位置,我们检查其四个相邻位置(上、下、左、右)。如果相邻位置在地图范围内、未被访问过、且高度差异满足上坡或下坡的条件,则我们将其标记为已访问,并递归地继续DFS。
  4. 回溯

    • 在每次递归调用返回后,我们需要将当前位置标记为未访问,以便在后续的DFS中能够重新访问它(回溯)。
  5. 更新最长路径

    • 在每次DFS完成后,我们更新max_moves为当前找到的最长路径长度(注意要减去1,因为我们在DFS中计算的是从当前点到终点的长度,而我们需要的是从起点到终点的总长度)。
  6. 返回结果

    • 遍历完所有起点后,max_moves将包含最长的移动路径长度,我们将其作为结果返回。

代码分析

1.主函数和初始化

def solution(rows, cols, height_map): max_moves = 0 visited = [[False] * cols for _ in range(rows)] # 从每个点开始进行 DFS for row in range(rows): for col in range(cols): max_moves = max(max_moves, dfs(height_map, visited, row, col, 0, rows, cols) - 1) return max_moves
  • solution函数是程序的入口点,它接收地图的行数rows、列数cols和高度矩阵height_map作为输入。
  • max_moves变量用于记录最长的移动路径长度,初始化为0。
  • visited矩阵用于跟踪哪些位置已经被访问过,以避免重复访问。其大小与地图相同,初始化为False
  • 使用两个嵌套的for循环遍历地图上的每个点,作为潜在的起点。
  • 对于每个起点,调用dfs函数进行深度优先搜索,并将找到的最长路径长度(减1,因为dfs计算的是从当前点到终点的长度,而我们需要的是从起点到终点的总长度)与max_moves进行比较,更新max_moves为较大值。
  • 最后,返回max_moves作为结果。

2.深度优先搜索(DFS)

def dfs(height_map, visited, current_row, current_col, last_move, rows, cols):
    visited[current_row][current_col] = True
    max_length = 1  # 当前路径长度
    row_directions = [-1, 1, 0, 0]  # 上下移动
    col_directions = [0, 0, -1, 1]  # 左右移动
 
    for direction in range(4):
        next_row = current_row + row_directions[direction]
        next_col = current_col + col_directions[direction]
 
        # 判断新坐标是否在地图范围内且未被访问过
        if 0 <= next_row < rows and 0 <= next_col < cols and not visited[next_row][next_col]:
            height_difference = height_map[next_row][next_col] - height_map[current_row][current_col]
            if height_difference != 0:  # 不能走到高度相同的点
                # ...(省略了移动逻辑,见下一部分分析)
 
    visited[current_row][current_col] = False  # 回溯
    return max_length

3.移动逻辑

if last_move == 0:
                    # 起点,可以上坡或下坡
                    can_move = True
                    new_last_move = 1 if height_difference > 0 else 2
                elif last_move == 1 and height_difference < 0:
                    # 上一次是上坡,下一次必须下坡
                    can_move = True
                    new_last_move = 2
                elif last_move == 2 and height_difference > 0:
                    # 上一次是下坡,下一次必须上坡
                    can_move = True
                    new_last_move = 1
                
                if can_move:
                    length = 1 + dfs(height_map, visited, next_row, next_col, new_last_move, rows, cols)
                    max_length = max(max_length, length)
                        visited[current_row][current_col] = False # 回溯 
                        return max_length 
  • 这部分代码位于dfs函数内部,用于判断是否可以移动到下一个位置,并更新移动逻辑。
  • 如果last_move为0,表示当前位置是起点,可以上坡或下坡,因此can_move设置为True,并根据高度差设置new_last_move为1(上坡)或2(下坡)。
  • 如果last_move为1,表示上一次是上坡,因此下一次必须下坡(height_difference < 0),如果满足条件,则can_move设置为Truenew_last_move设置为2。
  • 如果last_move为2,表示上一次是下坡,因此下一次必须上坡(height_difference > 0),如果满足条件,则can_move设置为Truenew_last_move设置为1。
  • 如果can_moveTrue,则递归地调用dfs函数,并将返回的路径长度加1后与max_length进行比较,更新max_length为较大值。

总结

上述代码通过深度优先搜索(DFS)算法,在给定高度地图的m × n网格中,寻找满足上坡下坡交替条件的最长路径。每个位置仅能被访问一次,且移动需基于高度差异。代码遍历所有起点,使用DFS探索路径,并记录最长路径长度。