问题描述
小U决定在一个 𝑚 × 𝑛 m×n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:
只能上坡或者下坡,不能走到高度相同的点。 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。 每个位置只能经过一次,不能重复行走。 任务是帮助小U找到他在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。
例如在以下2x2的地图中:
1 2 4 3 中庸行者可以选择移动顺序 3 -> 4 -> 1 -> 2,最大移动次数为3。
测试样例
样例1:
输入:m = 2, n = 2, a = [[1, 2], [4, 3]] 输出:3
样例2:
输入:m = 3, n = 3, a = [[10, 1, 6], [5, 9, 3], [7, 2, 4]] 输出:8
样例3:
输入:m = 4, n = 4, a = [[8, 3, 2, 1], [4, 7, 6, 5], [12, 11, 10, 9], [16, 15, 14, 13]] 输出:11
def solution(m: int, n: int, a: list) -> int: # 初始化访问标记数组 visited = [[False] * n for _ in range(m)]
def dfs(x, y, is_uphill):
# 标记当前位置为已访问
visited[x][y] = True
# 初始化最大步数
max_steps = 0
# 尝试向四个方向移动
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
# 检查边界和是否未访问
if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny]:
# 检查是否满足交替上坡下坡的条件
if is_uphill and a[nx][ny] > a[x][y]:
max_steps = max(max_steps, 1 + dfs(nx, ny, False))
elif not is_uphill and a[nx][ny] < a[x][y]:
max_steps = max(max_steps, 1 + dfs(nx, ny, True))
# 回溯,标记当前位置为未访问
visited[x][y] = False
return max_steps
# 初始化最大步数
max_moves = 0
# 从每个位置开始尝试
for i in range(m):
for j in range(n):
max_moves = max(max_moves, dfs(i, j, True), dfs(i, j, False))
return max_moves
问题理解
地图和移动规则:
你有一个 m x n 的地图,每个位置都有一个高度值。 小U只能在满足以下条件的情况下移动: 只能上坡或者下坡,不能走到高度相同的点。 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。 每个位置只能经过一次,不能重复行走。
目标:
找到小U在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。
数据结构选择
访问标记数组: 使用一个二维数组 visited 来记录每个位置是否已经被访问过。
DFS 深度优先搜索: 使用 DFS 来探索所有可能的路径。DFS 适合这种需要遍历所有可能路径的问题。
算法步骤
初始化: 初始化一个 visited 数组,用于记录每个位置是否已经被访问过。
DFS 函数: 定义一个 DFS 函数,该函数接受当前位置 (x, y) 和当前的移动方向(上坡或下坡)作为参数。 在 DFS 函数中,标记当前位置为已访问。 尝试向四个方向(上、下、左、右)移动,检查是否满足移动条件(边界、未访问、交替上坡下坡)。 如果满足条件,递归调用 DFS 函数,并更新最大步数。 回溯时,标记当前位置为未访问。
主函数: 从每个位置开始尝试,调用 DFS 函数,并记录最大步数。
反思:为什么在DFS函数中需要回溯?
避免重复访问:
在DFS中,我们使用一个 visited 数组来记录每个位置是否已经被访问过。如果不进行回溯,一旦某个位置被标记为已访问,就无法再次访问它,这会限制我们探索其他可能的路径。 通过回溯,我们可以在探索完一条路径后,将当前位置重新标记为未访问,从而允许其他路径再次访问这个位置。
探索所有可能的路径:
回溯确保我们能够探索所有可能的路径,而不仅仅是一条路径。如果不进行回溯,DFS 只会沿着一条路径一直走到底,而不会尝试其他可能的路径。 通过回溯,我们可以在每条路径的末尾返回到上一个节点,继续探索其他方向,从而找到所有可能的路径。
总结
使用 DFS 来探索所有可能的路径。 使用 visited 数组来记录每个位置是否已经被访问过。 确保移动是交替进行的(上坡后下坡,下坡后上坡)。 从每个位置开始尝试,记录最大步数。