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

13 阅读3分钟

问题描述

小U决定在一个 m×nm×n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:

  1. 只能上坡或者下坡,不能走到高度相同的点。
  2. 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。
  3. 每个位置只能经过一次,不能重复行走。

任务是帮助小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

解题思路

  1. 深度优先搜索(DFS)
    - 用 DFS 遍历所有可能的路径,从每个点开始搜索。
    - 利用递归,从一个点开始搜索所有可能的方向,记录路径长度。

  2. 交替上下规则
    - 增加一个状态变量 isUp,标识当前路径是“上升”还是“下降”。
    - 根据 isUp,决定路径是否可以继续。

  3. 回溯
    - 使用 visited 数组记录访问状态,防止重复访问。
    - 每次 DFS 结束后回溯状态,将当前点重新标记为未访问。

  4. 主函数
    - 遍历矩阵中所有点,分别以“上升”和“下降”状态作为起点,记录最长路径。

代码逐步解析

  1. DFS 函数
    - 参数:
    - x, y:当前坐标。
    - isUp:当前状态(上升或下降)。
    - a:矩阵。
    - visited:标记数组。
    - 逻辑:
    - 遍历四个方向。
    - 根据 isUp 判断是否满足上下交替规则,若满足,递归调用 DFS。

  2. 主函数 solution
    - 初始化 visited 数组。
    - 对每个矩阵点 (i, j) 调用两次 DFS:
    - 一次以“上升”状态为起点。
    - 一次以“下降”状态为起点。
    - 记录最长路径。

  3. 主程序
    - 提供多个测试用例,验证代码正确性。

代码答案

#include <vector>
#include <algorithm>
using namespace std;

// 深度优先搜索,计算最长路径
int dfs(int x, int y, bool isUp, vector<vector<int>>& a, vector<vector<bool>>& visited) {
    int m = a.size(), n = a[0].size(), maxSteps = 0;
    visited[x][y] = true;

    for (auto [dx, dy] : vector<pair<int, int>>{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}) {
        int nx = x + dx, ny = y + dy;
        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]))
                maxSteps = max(maxSteps, 1 + dfs(nx, ny, !isUp, a, visited));
        }
    }

    visited[x][y] = false; // 回溯
    return maxSteps;
}

// 计算矩阵的最长交替路径
int solution(int m, int n, vector<vector<int>>& a) {
    int maxSteps = 0;
    vector<vector<bool>> visited(m, vector<bool>(n, false));
    for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j)
            maxSteps = max({maxSteps, dfs(i, j, true, a, visited), dfs(i, j, false, a, visited)});
    return maxSteps;
}

int main() {
    // 显式初始化二维向量
    vector<vector<int>> a1 = {{1, 2}, {4, 3}};
    vector<vector<int>> a2 = {{10, 1, 6}, {5, 9, 3}, {7, 2, 4}};
    vector<vector<int>> a3 = {{8, 3, 2, 1}, {4, 7, 6, 5}, {12, 11, 10, 9}, {16, 15, 14, 13}};
    
    // 测试用例
    cout << (solution(2, 2, a1) == 3) << endl;
    cout << (solution(3, 3, a2) == 8) << endl;
    cout << (solution(4, 4, a3) == 11) << endl;

    return 0;
}

测试样例

    vector<vector<int>> a1 = {{1, 2}, {4, 3}};  
    vector<vector<int>> a2 = {{10, 1, 6}, {5, 9, 3}, {7, 2, 4}};  
    vector<vector<int>> a3 = {{8, 3, 2, 1}, {4, 7, 6, 5}, {12, 11, 10, 9}, {16, 15, 14, 13}};  
      
    cout << (solution(2, 2, a1) == 3) << endl;  // 最长路径:4 → 2 → 1  
    cout << (solution(3, 3, a2) == 8) << endl;  // 最长路径:10 → 9 → 5 → 6 → 7 → 2 → 3 → 4  
    cout << (solution(4, 4, a3) == 11) << endl; // 最长路径:16 → 15 → 14 → 13 → 9 → 10 → 11 → 12 → 8 → 7 → 3  
}

生活中的应用

  1. 爬山与滑雪路径规划
    - 设计最佳路线,满足“先上升再下降”的需求。
    - 类似于游戏中规划复杂路径的逻辑。

  2. 股票涨跌分析
    - 找到一段时间内,股价的最大“涨跌交替”路径。