题目
小U决定在一个 𝑚×𝑛m×n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:
- 只能上坡或者下坡,不能走到高度相同的点。
- 移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。
- 每个位置只能经过一次,不能重复行走。
任务是帮助小U找到他在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。
例如在以下2x2的地图中:
1 2
4 3
中庸行者可以选择移动顺序 3 -> 4 -> 1 -> 2,最大移动次数为3。
为了解决这个问题,我们可以采用深度优先搜索(DFS)的策略。
解题思路
-
初始化:创建一个与地图大小相同的二维布尔数组
visited,用于记录每个位置是否已经被访问过。 -
深度优先搜索(DFS) :定义一个递归函数
dfs,它接受当前位置的坐标(x, y)和一个布尔值isUp,表示当前是上坡还是下坡。 -
递归过程:
- 标记当前位置为已访问。
- 尝试从当前位置向四个方向移动(上、下、左、右)。
- 对于每个方向,检查是否越界以及是否已经访问过。
- 如果满足上坡或下坡的条件(根据
isUp的值),则递归调用dfs函数,并更新最大路径长度。 - 在递归返回前,回溯当前位置的访问状态,以便在其他路径中使用。
-
遍历地图:在主函数中,遍历地图的每个位置,从每个位置开始分别尝试上坡和下坡的DFS,并记录下最大的移动次数。
-
返回结果:由于每次递归调用都会将当前位置计入路径长度,最终的结果需要减去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在地图上行走的问题,并找到他在符合所有条件的前提下能走过的最大连续位置数量。