问题描述
小U决定在一个 m×nm×n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:
- 只能上坡或者下坡,不能走到高度相同的点。
- 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。
- 每个位置只能经过一次,不能重复行走。
任务是帮助小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
解题思路
-
深度优先搜索(DFS):
- 用 DFS 遍历所有可能的路径,从每个点开始搜索。
- 利用递归,从一个点开始搜索所有可能的方向,记录路径长度。 -
交替上下规则:
- 增加一个状态变量isUp
,标识当前路径是“上升”还是“下降”。
- 根据isUp
,决定路径是否可以继续。 -
回溯:
- 使用visited
数组记录访问状态,防止重复访问。
- 每次 DFS 结束后回溯状态,将当前点重新标记为未访问。 -
主函数:
- 遍历矩阵中所有点,分别以“上升”和“下降”状态作为起点,记录最长路径。
代码逐步解析
-
DFS 函数:
- 参数:
-x, y
:当前坐标。
-isUp
:当前状态(上升或下降)。
-a
:矩阵。
-visited
:标记数组。
- 逻辑:
- 遍历四个方向。
- 根据isUp
判断是否满足上下交替规则,若满足,递归调用 DFS。 -
主函数
solution
:
- 初始化visited
数组。
- 对每个矩阵点(i, j)
调用两次 DFS:
- 一次以“上升”状态为起点。
- 一次以“下降”状态为起点。
- 记录最长路径。 -
主程序:
- 提供多个测试用例,验证代码正确性。
代码答案
#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
}
生活中的应用
-
爬山与滑雪路径规划:
- 设计最佳路线,满足“先上升再下降”的需求。
- 类似于游戏中规划复杂路径的逻辑。 -
股票涨跌分析:
- 找到一段时间内,股价的最大“涨跌交替”路径。