伪代码
function findLongestSlope(R, C, heights): max_slope_length = 0 for i from 1 to R: for j from 1 to C: slope_length = DFS(i, j, heights) max_slope_length = max(max_slope_length, slope_length) return max_slope_length function DFS(x, y, heights): // 当前点作为起点进行深度优先搜索 // 初始滑坡长度为1 current_slope_length = 1 for each direction (dx, dy) from (x, y): new_x = x + dx new_y = y + dy // 如果新点在区域内,并且高度低于当前点,则继续搜索 if isValid(new_x, new_y) and heights[new_x][new_y] < heights[x][y]: slope_length = 1 + DFS(new_x, new_y, heights) // 更新最长滑坡长度 current_slope_length = max(current_slope_length, slope_length) return current_slope_length function isValid(x, y): // 检查新点是否在区域内 return 1 <= x <= R and 1 <= y <= C
#include <stdio.h> #define MAX_SIZE 100 int R, C; int matrix[MAX_SIZE][MAX_SIZE]; int dp[MAX_SIZE][MAX_SIZE]; // 定义四个方向的偏移量(四个方向找的固定格式) int dx[4] = { -1, 1, 0, 0 }; int dy[4] = { 0, 0, -1, 1 }; // 从位置 (x, y) 开始找最长滑坡的长度 int dfs(int x, int y) { if (dp[x][y] != 0) { return dp[x][y]; } dp[x][y] = 1; // 初始值为1 // 尝试向四个方向滑动 for (int i = 0; i < 4; i++) { int nx = x + dx[i]; int ny = y + dy[i]; // 判断是否越界以及高度是否递减 if (nx >= 0 && nx < R && ny >= 0 && ny < C && matrix[nx][ny] < matrix[x][y]) { dp[x][y] = (dp[x][y] > dfs(nx, ny) + 1) ? dp[x][y] : dfs(nx, ny) + 1;//更新局部最优 } } return dp[x][y]; } int main() { scanf("%d %d", &R, &C); for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { scanf("%d", &matrix[i][j]); } } int longest_slope = 0; // 对每个位置调用 dfs for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { longest_slope = (longest_slope > dfs(i, j)) ? longest_slope : dfs(i, j);//全局最优比较 } } printf("%d\n", longest_slope); return 0; }
整体思路如下:
- 从每个点出发,以该点为起点进行深度优先搜索(DFS)。
- 在搜索过程中,判断当前点是否可以向下滑行,即比其周围相邻点的高度低,如果可以向下滑行,则继续搜索下一个相邻点,并更新滑坡长度(更新局部最优)。
- 搜索过程中记录每个点处得到的最长滑坡长度,最终输出最大的滑坡长度即可(全局最优的比较)。
ps:
1.if (dp[x][y] != 0) { return dp[x][y]; }这个是为了避免重复计算同一个点。
1 2 3 4 5 6 7 8 9
比如dp记录了5的最优路径是长度,则下一个点6向左的话,直接用5记录好的最优长度5即可。
2.dp[x][y] = (dp[x][y] > dfs(nx, ny) + 1) ? dp[x][y] : dfs(nx, ny) + 1;怎么理解
这行代码的作用是更新当前位置
(x, y)
的最优值dp[x][y]
。它的意思可以理解为:
- 如果当前位置
(x, y)
的最优值已经被计算过,并且已经存储在dp[x][y]
中,那么我们比较已经存储的最优值dp[x][y]
和从(nx, ny)
位置出发进行深度优先搜索得到的最优值dfs(nx, ny) + 1
,然后选择其中较大的值作为当前位置(x, y)
的最优值。- 如果当前位置
(x, y)
的最优值尚未被计算过,即dp[x][y]
的值为 0,那么我们直接将从(nx, ny)
位置出发进行深度优先搜索得到的最优值dfs(nx, ny) + 1
作为当前位置(x, y)
的最优值。这样做的目的是确保我们每次更新
dp[x][y]
的值时,都能选择最优的结果。如果当前位置已经有最优值存储在dp[x][y]
中,我们就不需要重新计算,而是比较已有的最优值和新的可能性中的最优值,选择更大的那个作为当前位置的最优值。
3.为什么要 dfs(nx, ny) + 1而不是 dfs(nx, ny)
在这个问题中,我们需要找到从当前位置
(x, y)
出发的最长滑坡长度。当我们从当前位置(x, y)
转移到相邻位置(nx, ny)
时,这一步的长度是 1,因为我们每次只能移动到相邻位置。因此,我们需要将当前位置(x, y)
的最优值更新为从相邻位置(nx, ny)
出发的最优值dfs(nx, ny)
加上当前步的长度 1,即dfs(nx, ny) + 1
。换句话说,我们考虑的是从当前位置
(x, y)
出发的最长滑坡,因此需要将当前位置的最优值更新为从相邻位置(nx, ny)
出发的最长滑坡长度加上当前这一步的长度 1。