问题描述 小U决定在一个 m × n m×n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动: 只能上坡或者下坡,不能走到高度相同的点。 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。 每个位置只能经过一次,不能重复行走。 任务是帮助小U找到他在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。 例如在以下2x2的地图中: 1 2 4 3 中庸行者可以选择移动顺序 3 -> 4 -> 1 -> 2,最大移动次数为3
问题分析
这是一个关于地图路径搜索的典型问题。我们需要在给定的地图中找到小U可以移动的最大次数,遵循以下规则:
- 只能上下坡:当前点到下一个点的高度必须不同。
- 交替移动:必须交替上坡和下坡,不能连续上坡或连续下坡。
- 不重复经过点:每个点只能经过一次。
本质上,这是一个 有约束的深度优先搜索(DFS) 问题,需要在地图上遍历所有可能的路径并记录最大移动次数。
解题思路
-
表示地图与方向
用二维数组grid[m][n]表示地图,其中每个元素为地形高度。同时定义上下左右四个方向的偏移量directions,用于控制搜索方向。 -
状态存储
- 当前点的坐标
(x, y)。 - 上一次的移动状态:上坡还是下坡,用一个布尔值
is_ascend来表示。如果当前移动是上坡,则下一次必须是下坡。
- 当前点的坐标
-
DFS 搜索
-
从地图上的任意一个点
(i, j)出发。 -
判断从当前位置是否可以移动到某一方向的下一个点
(nx, ny):(nx, ny)在地图范围内。(nx, ny)没有被访问过。- 高度满足上坡或下坡的条件。
-
更新状态并继续递归搜索,记录路径长度。
-
搜索完成后回溯,恢复状态,探索其他方向。
-
-
优化
使用一个二维数组dp[x][y]来存储从某点开始的最长路径长度,避免重复计算。 -
输出结果
遍历所有起点,找到最大路径长度。
实现代码
以下是基于上述思路的完整实现代码:
def longest_path(grid):
m, n = len(grid), len(grid[0])
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
max_steps = 0
dp = [[[-1, -1] for _ in range(n)] for _ in range(m)] # dp[x][y][0] 表示上坡后最长路径,dp[x][y][1] 表示下坡后最长路径
def dfs(x, y, is_ascend, visited):
if dp[x][y][int(is_ascend)] != -1:
return dp[x][y][int(is_ascend)]
visited[x][y] = True
max_len = 0
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny]:
if is_ascend and grid[nx][ny] < grid[x][y]: # 下坡
max_len = max(max_len, 1 + dfs(nx, ny, False, visited))
elif not is_ascend and grid[nx][ny] > grid[x][y]: # 上坡
max_len = max(max_len, 1 + dfs(nx, ny, True, visited))
visited[x][y] = False
dp[x][y][int(is_ascend)] = max_len
return max_len
for i in range(m):
for j in range(n):
visited = [[False] * n for _ in range(m)]
max_steps = max(max_steps, dfs(i, j, True, visited)) # 从 (i, j) 开始,上坡
max_steps = max(max_steps, dfs(i, j, False, visited)) # 从 (i, j) 开始,下坡
return max_steps
测试用例
输入示例 1:
grid = [ [1, 2],
[4, 3]
]
print(longest_path(grid)) # 输出: 3
输入示例 2:
grid = [ [1, 3, 2],
[6, 5, 4],
[7, 8, 9]
]
print(longest_path(grid)) # 输出: 7
输入示例 3:
grid = [ [10, 20, 30],
[15, 25, 35],
[5, 50, 40]
]
print(longest_path(grid)) # 输出: 5
复杂度分析
-
时间复杂度:
- 最差情况下,每个点都需要尝试上下坡两种状态,并且对每个状态进行深度优先搜索。
- 时间复杂度为 O(m×n×4k)O(m \times n \times 4^k),其中 kk 是路径的最大长度。
-
空间复杂度:
- 使用了一个
dp数组存储结果,大小为 O(m×n)O(m \times n)。 - 递归栈的最大深度为 O(k)O(k),所以空间复杂度为 O(m×n+k)O(m \times n + k)。
- 使用了一个
总结
通过动态规划结合深度优先搜索,我们可以有效地求解满足题目约束条件的最长路径问题。dp 的使用显著优化了重复计算,适合解决复杂约束的路径搜索问题。