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

146 阅读5分钟

今天我们将在豆包MarsCode AI刷题平台上,完成《小U的最大连续移动次数问题》这个算法问题,通过练习提升用户解决此类问题的能力。

《小U的最大连续移动次数问题》题目如下:

image.png

问题理解

  1. 地图和移动规则

    • 你有一个 m x n 的地图,每个位置有一个高度值。
    • 小U只能上坡或下坡,但不能走到高度相同的点。
    • 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡。
    • 每个位置只能经过一次,不能重复行走。
  2. 目标

    • 找到小U在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。

数据结构选择

  • 地图表示:使用二维数组 a 来表示地图。
  • 访问状态:使用一个二维数组 visited 来记录每个位置是否已经被访问过。
  • 方向数组:使用一个方向数组来表示上下左右四个方向的移动。

算法步骤

  1. 初始化

    • 创建一个 visited 数组,初始化为 False,表示所有位置都未被访问。
    • 创建一个方向数组 directions,表示上下左右四个方向的移动。
  2. 深度优先搜索 (DFS)

    • 从每个未访问的位置开始,进行深度优先搜索。
    • 在DFS过程中,记录当前路径的长度,并更新最大路径长度。
    • 每次移动时,检查是否满足上坡或下坡的条件,并且不能重复访问。
  3. 交替移动

    • 在DFS过程中,记录上一次的移动是上坡还是下坡,确保本次移动与之相反。
  4. 返回结果

    • 最终返回最大路径长度。

具体实现

#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)过程中,我们需要特别注意以下几点:

边界情况处理

  1. 地图边界

    • 在移动时,确保不会超出地图的边界。例如,如果当前位置是 (i, j),那么移动时需要检查 i 和 j 是否在合法范围内(即 0 <= i < m 和 0 <= j < n)。
  2. 访问状态

    • 在移动时,确保不会访问已经访问过的位置。使用 visited 数组来记录每个位置的访问状态,并在访问后将其标记为 True
  3. 交替移动

    • 在移动时,确保满足交替移动的规则。即上坡后必须下坡,下坡后必须上坡。

代码示例

以下是一个处理边界情况的代码示例:

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)

解释

  1. 方向数组directions 用于表示上下左右四个方向的移动。
  2. 访问状态数组visited 用于记录每个位置是否已经被访问过。
  3. DFS函数dfs 函数用于进行深度优先搜索,处理边界情况并确保满足交替移动的规则。
  4. 主函数:从每个未访问的位置开始DFS,并更新最大路径长度。

通过这种方式,可以有效地处理地图中的边界情况,并确保算法正确性。