今天我们将在豆包MarsCode AI刷题平台上,完成《小U的最大连续移动次数问题》这个算法问题,通过练习提升用户解决此类问题的能力。
《小U的最大连续移动次数问题》题目如下:
问题理解
-
地图和移动规则:
- 你有一个
m x n的地图,每个位置有一个高度值。 - 小U只能上坡或下坡,但不能走到高度相同的点。
- 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡。
- 每个位置只能经过一次,不能重复行走。
- 你有一个
-
目标:
- 找到小U在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。
数据结构选择
- 地图表示:使用二维数组
a来表示地图。 - 访问状态:使用一个二维数组
visited来记录每个位置是否已经被访问过。 - 方向数组:使用一个方向数组来表示上下左右四个方向的移动。
算法步骤
-
初始化:
- 创建一个
visited数组,初始化为False,表示所有位置都未被访问。 - 创建一个方向数组
directions,表示上下左右四个方向的移动。
- 创建一个
-
深度优先搜索 (DFS):
- 从每个未访问的位置开始,进行深度优先搜索。
- 在DFS过程中,记录当前路径的长度,并更新最大路径长度。
- 每次移动时,检查是否满足上坡或下坡的条件,并且不能重复访问。
-
交替移动:
- 在DFS过程中,记录上一次的移动是上坡还是下坡,确保本次移动与之相反。
-
返回结果:
- 最终返回最大路径长度。
具体实现
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int solution(int m, int n, vector<vector<int>>& a) {
// 初始化visited数组
vector<vector<bool>> visited(m, vector<bool>(n, false));
// 定义DFS函数
function<int(int, int, bool)> dfs = [&](int x, int y, bool isUp) -> int {
// 标记当前位置为已访问
visited[x][y] = true;
int maxPath = 0;
// 尝试向四个方向移动
vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (auto& dir : directions) {
int nx = x + dir.first;
int ny = y + dir.second;
// 检查边界和是否已访问
if (nx >= 0 && nx < m && ny >= 0 && ny < n && !visited[nx][ny]) {
// 检查是否满足上坡或下坡条件
if ((isUp && a[nx][ny] < a[x][y]) || (!isUp && a[nx][ny] > a[x][y])) {
// 递归调用DFS
maxPath = max(maxPath, dfs(nx, ny, !isUp));
}
}
}
// 回溯:标记当前位置为未访问
visited[x][y] = false;
// 返回当前路径长度
return maxPath + 1;
};
int maxSteps = 0;
// 遍历地图中的每个位置,尝试从该位置开始DFS
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
maxSteps = max(maxSteps, dfs(i, j, true));
maxSteps = max(maxSteps, dfs(i, j, false));
}
}
return maxSteps - 1;
}
int main() {
vector<vector<int>> a1 = {{1, 2}, {4, 3}};
cout << (solution(2, 2, a1) == 3) << endl;
vector<vector<int>> a2 = {{10, 1, 6}, {5, 9, 3}, {7, 2, 4}};
cout << (solution(3, 3, a2) == 8) << endl;
vector<vector<int>> a3 = {{8, 3, 2, 1}, {4, 7, 6, 5}, {12, 11, 10, 9}, {16, 15, 14, 13}};
cout << (solution(4, 4, a3) == 11) << endl;
}
如何处理地图中的边界情况?
处理地图中的边界情况是确保算法正确性的关键步骤之一。在深度优先搜索(DFS)过程中,我们需要特别注意以下几点:
边界情况处理
-
地图边界:
- 在移动时,确保不会超出地图的边界。例如,如果当前位置是
(i, j),那么移动时需要检查i和j是否在合法范围内(即0 <= i < m和0 <= j < n)。
- 在移动时,确保不会超出地图的边界。例如,如果当前位置是
-
访问状态:
- 在移动时,确保不会访问已经访问过的位置。使用
visited数组来记录每个位置的访问状态,并在访问后将其标记为True。
- 在移动时,确保不会访问已经访问过的位置。使用
-
交替移动:
- 在移动时,确保满足交替移动的规则。即上坡后必须下坡,下坡后必须上坡。
代码示例
以下是一个处理边界情况的代码示例:
def solution(m: int, n: int, a: list) -> int:
# 方向数组,表示上下左右四个方向的移动
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
# 初始化访问状态数组
visited = [[False] * n for _ in range(m)]
def dfs(x, y, last_height, is_up):
# 检查是否超出边界
if x < 0 or x >= m or y < 0 or y >= n:
return 0
# 检查是否已经访问过
if visited[x][y]:
return 0
# 检查是否满足交替移动的规则
current_height = a[x][y]
if (is_up and current_height <= last_height) or (not is_up and current_height >= last_height):
return 0
# 标记当前位置为已访问
visited[x][y] = True
# 计算当前路径长度
max_path = 0
for dx, dy in directions:
max_path = max(max_path, dfs(x + dx, y + dy, current_height, not is_up))
# 回溯,标记当前位置为未访问
visited[x][y] = False
# 返回当前路径长度
return max_path + 1
# 初始化最大路径长度
max_path_length = 0
# 从每个未访问的位置开始DFS
for i in range(m):
for j in range(n):
max_path_length = max(max_path_length, dfs(i, j, a[i][j], True))
return max_path_length
if __name__ == '__main__':
print(solution(2, 2, [[1, 2], [4, 3]]) == 3)
print(solution(3, 3, [[10, 1, 6], [5, 9, 3], [7, 2, 4]]) == 8)
print(solution(4, 4, [[8, 3, 2, 1], [4, 7, 6, 5], [12, 11, 10, 9], [16, 15, 14, 13]]) == 11)
解释
- 方向数组:
directions用于表示上下左右四个方向的移动。 - 访问状态数组:
visited用于记录每个位置是否已经被访问过。 - DFS函数:
dfs函数用于进行深度优先搜索,处理边界情况并确保满足交替移动的规则。 - 主函数:从每个未访问的位置开始DFS,并更新最大路径长度。
通过这种方式,可以有效地处理地图中的边界情况,并确保算法正确性。