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

100 阅读4分钟

1.问题

问题描述

小U决定在一个 m×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

2.思路

  • 通过 深度优先搜索(DFS) 来探测从每个位置开始的最大路径。

  • DFS 遍历方向:可以向上下左右四个方向移动。

  • 每次递归调用时,我们分别考虑两种情况:是否从上坡开始(up = true)或从下坡开始(up = false)。

    • 上坡( up = true :只能移动到比当前格子高度小的地方。
    • 下坡( up = false :只能移动到比当前格子高度大的地方。

3.代码

#include <bits/stdc++.h>
using namespace std;

int solution(int m, int n, vector<vector<int>>& a) {
    // write code here
    vector<vector<bool>> visited(m, vector<bool>(n, false));
    function<int(int, int, bool)> dfs = [&](int x, int y, bool up){
      int max_path = 0;
      vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
      visited[x][y] = true;
      //向四个方向移动
      for (auto& dir:directions){
        int next_x = x + dir.first;
        int next_y = y + dir.second;
        //不超边界且未访问
        if (next_x >= 0 && next_x < m && next_y >= 0 && next_y < n && !visited[next_x][next_y]){
          //满足上/下坡条件
          if(up && a[next_x][next_y] > a[x][y] || !up && a[next_x][next_y] < a[x][y]){
            max_path = max(max_path, dfs(next_x, next_y, !up));
          }
        }
      }
      //回溯,清除标记
      visited[x][y] = false;
      return max_path + 1;
    };
    int max_step = 0;
    for (int i = 0;i < m;i++){
      for(int j = 0;j<n;j ++){
        max_step = max(max_step, dfs(i, j, true));
        max_step = max(max_step, dfs(i, j, false));
      }
    }
    return max_step - 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;
}
  • vector<vector> visited(m, vector(n, false));

vector<bool>(n, false):创建一个包含 n 个元素的布尔向量,并将每个元素初始化为 false

vector<vector<bool>> visited(m, vector<bool>(n, false));:创建一个 mn 列的二维布尔向量,其中每个元素都初始化为 false

  • function<int(int, int, bool)> dfs = [&](int x, int y, bool up) -> int {

function<int(int, int, bool)>: 这里使用 std::function 来定义 dfs 的类型,它是一个接受两个整数(xy)以及一个布尔值(up)作为参数,并返回一个整数的函数类型。

dfs = [&](int x, int y, bool up) -> int { ... }: 这是一个 lambda 表达式,dfs 是它的名称。[&] 表示捕获外部作用域的变量,通过引用方式捕获。这意味着 dfs 函数可以访问并修改外部作用域中的变量。

  • vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}{0, 1}};

pair 是 C++ 标准库中定义的一个模板类,用于存储两个数据元素。pair 是一个通用容器,它将两个不同类型的值(可以是相同类型或不同类型)组合在一起,可以通过一个变量同时访问这两个值。

  • up

是一个布尔参数,用于表示当前的递归状态,指示搜索是否在进行“上坡”还是“下坡”。

作用:

up = true 表示当前正在进行 上坡,即下一个访问的格子必须要小于当前格子的高度,a[next_x][next_y] < a[x][y]

up = false 表示当前正在进行 下坡,即下一个访问的格子必须要大于当前格子的高度,a[next_x][next_y] > a[x][y]

  • max_step = max(max_step, dfs(i, j, true));

max_step = max(max_step, dfs(i, j, false));

对于每个位置 (i, j),分别进行上坡和下坡的深度优先搜索,更新 max_step 为两者中的较大值。

  • dfs 中的 return max_path + 1; :表示返回当前格子出发的最大路径长度,包括当前格子。solution 中的 return max_step - 1; :因为 dfs 已经包含了起点,最终返回路径长度时需要减去 1,以得到不包括起点的路径长度。

4.参考资料

【题解】小U的最大连续移动次数问题 | 豆包MarsCode AI刷题本文解析了小U在地图上行走的最大路径问题,采用DF - 掘金