小U的最大连续移动次数问题
问题描述
小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(x, y, sta):表示小U当前在 ,并且状态为sta(0 表示上坡,1 表示下坡)。- 从当前点出发,尝试向四个方向移动,找到所有符合条件的路径长度。
-
合法性检查:
-
确保移动后的位置在地图范围内。
-
不能走回已经访问过的位置。
-
判断高度关系是否符合当前状态要求:
sta = 0(上坡):目标点高度 > 当前点高度。sta = 1(下坡):目标点高度 < 当前点高度。
-
-
记录与回溯:
- 使用
visited数组记录已访问的位置,在递归结束后还原状态。
- 使用
-
全局搜索:
- 枚举地图上的每一个点作为起点,并分别从两种状态(上坡/下坡)开始搜索,更新最长路径长度。
代码实现
以下是基于上述思路的完整代码实现:
#include <bits/stdc++.h>
using namespace std;
// 四个方向移动
constexpr pair<int, int> dirs[] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int solution(int m, int n, vector<vector<int>>& a) {
// 记录访问状态
vector<vector<int>> visited(m, vector<int>(n, 0));
// DFS 搜索函数
auto dfs = [&](auto&& self, int x, int y, int sta) -> int {
int max_length = 0;
for (auto [dx, dy] : dirs) {
int nx = x + dx, ny = y + dy;
// 判断合法性
if (nx >= 0 && nx < m && ny >= 0 && ny < n && !visited[nx][ny]) {
// 上坡状态:目标点高度必须更高
if (sta == 0 && a[nx][ny] > a[x][y]) {
visited[nx][ny] = 1;
max_length = max(max_length, 1 + self(self, nx, ny, 1)); // 切换到下坡状态
visited[nx][ny] = 0;
}
// 下坡状态:目标点高度必须更低
else if (sta == 1 && a[nx][ny] < a[x][y]) {
visited[nx][ny] = 1;
max_length = max(max_length, 1 + self(self, nx, ny, 0)); // 切换到上坡状态
visited[nx][ny] = 0;
}
}
}
return max_length;
};
int max_steps = 0;
// 从每个点开始搜索
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
visited[i][j] = 1;
max_steps = max(max_steps, dfs(dfs, i, j, 0)); // 从上坡开始
max_steps = max(max_steps, dfs(dfs, i, j, 1)); // 从下坡开始
visited[i][j] = 0;
}
}
return max_steps;
}
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;
}