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

83 阅读3分钟

题目

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

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

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

例如在以下2x2的地图中:

1 2
4 3

中庸行者可以选择移动顺序 3 -> 4 -> 1 -> 2,最大移动次数为3。

为了解决这个问题,我们可以采用深度优先搜索(DFS)的策略。

解题思路

  1. 初始化:创建一个与地图大小相同的二维布尔数组visited,用于记录每个位置是否已经被访问过。

  2. 深度优先搜索(DFS) :定义一个递归函数dfs,它接受当前位置的坐标(x, y)和一个布尔值isUp,表示当前是上坡还是下坡。

  3. 递归过程

    • 标记当前位置为已访问。
    • 尝试从当前位置向四个方向移动(上、下、左、右)。
    • 对于每个方向,检查是否越界以及是否已经访问过。
    • 如果满足上坡或下坡的条件(根据isUp的值),则递归调用dfs函数,并更新最大路径长度。
    • 在递归返回前,回溯当前位置的访问状态,以便在其他路径中使用。
  4. 遍历地图:在主函数中,遍历地图的每个位置,从每个位置开始分别尝试上坡和下坡的DFS,并记录下最大的移动次数。

  5. 返回结果:由于每次递归调用都会将当前位置计入路径长度,最终的结果需要减去1,以得到正确的最大移动次数。

代码注释

// 初始化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));
    }
}
// 返回最大移动次数,减去1是因为起始位置被计算了一次
return maxSteps - 1;

通过以上步骤,我们可以有效地解决小U在地图上行走的问题,并找到他在符合所有条件的前提下能走过的最大连续位置数量。