问题描述
小U决定在一个 m x n 的地图上行走。地图中的每个位置都有一个高度,表示地形的高低。小U只能在满足以下条件的情况下移动:
- 高度差条件:只能上坡或者下坡,不能走到高度相同的点。
- 交替移动条件:移动时必须交替进行:上坡后必须下坡,下坡后必须上坡,不能连续上坡或下坡。
- 不重复行走:每个位置只能经过一次,不能重复行走。
任务是帮助小U找到他在地图上可以移动的最大次数,即在符合所有条件的前提下,小U能走过的最大连续位置数量。
测试样例
样例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是一种非常适合探索所有可能路径的算法,尤其是在需要回溯的情况下。
对于DFS,我们要确定三个条件:函数参数,终止条件,搜索过程。
对于函数参数,我们每次搜索的时候都需要知道当前的位置,当前要进行上坡还是下坡,以及已经走过的步数,所以确定了函数参数为x,y,is_up,cur_step.
对于终止条件,因为我们要找到移动的最大次数,所以终止条件就是没有可以继续走的路,即走到函数结尾。
对于搜索过程,我们在dfs函数中,首先标记当前点为已访问,并更新max_moves。
然后遍历四个方向,对于每个方向,计算下一个点的坐标。如果下一个点在数组范围内且未被访问,则根据当前点是否是上坡和下一个点的值与当前点的值的比较结果,决定是否继续搜索。 在搜索完成后,回溯,将当前点标记为未访问。
最后,对于二维数组中的每个点,分别以该点为起点,分别进行上坡和下坡的搜索。
代码实现
int solution(int m, int n, vector<vector<int>>& a) {
vector<vector<bool>> visited(m,vector<bool>(n,false));
int max_moves = 0;
vector<int> dx = {1,-1,0,0};
vector<int> dy = {0,0,1,-1};
function<void(int , int , bool ,int)> dfs = [&]
(int x,int y ,bool is_up,int cur_move){
visited[x][y] = true;
max_moves = max(max_moves,cur_move);
for(int i=0;i<4;i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && nx <m && ny >=0 && ny < n && !visited[nx][ny])
{
if(is_up && a[x][y] < a[nx][ny])
{
dfs(nx,ny,false,cur_move+1);
}
if(!is_up && a[x][y] > a[nx][ny])
{
dfs(nx,ny,true,cur_move+1);
}
}
}
//回溯
visited[x][y] = false;
};
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
dfs(i,j,false,0);//下坡开始
dfs(i,j,true,0);//上坡开始
}
}
return max_moves;
}
总结
算法的时间复杂度为O(mn4^k),其中m和n是二维数组的行数和列数,k是从一个点到另一个点的最大路径长度。这个由于算法涉及到递归和回溯,因此在实际应用中可能会遇到性能问题,特别是在二维数组很大或者路径很长的情况下。