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

63 阅读4分钟

问题描述

小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. 地图移动规则

    • 小U只能在高度不同的位置之间移动。即高度相同的跳过
    • 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡。需要一个变量来记录上一次移动是上坡还是下坡
    • 每个位置只能经过一次,不能重复行走。需要定义一个vis数组来存储是否被访问过,要记得回溯。
  2. 目标

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

数据结构

  • 二维数组:用于表示地图的高度。
  • 访问标记数组:用于记录每个位置是否已经被访问过。

算法步骤

  1. 深度优先搜索 (DFS)

    • 从每个位置开始,进行深度优先搜索,尝试找到最长的路径。
    • 在DFS过程中,需要记录当前的移动方向(上坡或下坡),并确保下一次移动的方向与当前方向相反
  2. 状态记录

    • 在DFS过程中,需要记录每个位置的访问状态,以避免重复访问。
    • 每次移动时,更新当前位置的访问状态,并在回溯时恢复状态。
  3. 边界条件

    • 确保移动不会超出地图的边界。
    • 确保移动到的位置高度与当前位置不同。

代码分析

通过深度优先搜索(DFS)来遍历地图,确保每次移动都符合题目要求的交替上坡和下坡规则。通过递归调用DFS,计算从每个位置开始的最大移动次数,并更新全局最大值。整体思路清晰,逻辑正确。

  • dx 和 dy 数组用于表示四个方向的移动:上、右、下、左。

  • xy:当前位置的坐标。

  • d:上一次移动的方向,-1表示上一次是下坡,1表示上一次是上坡,0表示初始状态。

  • vis:访问标记数组,记录每个位置是否已经被访问过。

  • a:地图的高度数组。

  • mn:地图的行数和列数。

  • 逻辑

    • 遍历四个方向,计算新的坐标 nxny
    • 检查新坐标是否越界,是否已经被访问过,以及是否与当前位置高度相同。
    • 检查当前移动方向是否符合交替规则(上坡后必须下坡,下坡后必须上坡)。
    • 如果符合条件,标记新位置为已访问,并递归调用DFS。
    • 在回溯时,恢复新位置的访问状态。
#include <iostream>
#include <vector>
using namespace std;

int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};

// d为-1表示上一次下坡,d为1表示上一次上坡
int dfs(int x, int y, int d, vector<vector<int>> vis, vector<vector<int>> a, int m, int n) {
    int t = 0;
    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i], ny = y + dy[i];
        if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
        if (vis[nx][ny]) continue;
        if (a[nx][ny] == a[x][y]) continue;
        if (d == 0 || (d == 1 && a[x][y] > a[nx][ny]) || (d == -1 && a[x][y] < a[nx][ny])) {
            vis[nx][ny] = 1;
            int td = 0;
            if (a[nx][ny] > a[x][y]) td = 1;
            else if (a[nx][ny] < a[x][y]) td = -1;
            t = max(t, 1 + dfs(nx, ny, td, vis, a, m, n));
            vis[nx][ny] = 0;
        }
    }
    return t;
}

int solution(int m, int n, vector<vector<int>>& a) {
    int res = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            vector<vector<int>> vis(m, vector<int>(n, 0));
            vis[i][j] = 1;
            int x = dfs(i, j, 0, vis, a, m, n);
            // cout << "www " << x << endl;
            res = max(res, x);
        }
    }
    return res;
}

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;
}