关键词:DFS 、 记忆化搜索 、 动态规划
核心思想:使用DFS结合记忆化搜索来解决问题。记忆化搜索可以避免重复计算已经访问过的节点,从而提高效率。
解题步骤:
- 读取输入,初始化矩阵
mat
存储滑雪场的高度信息,初始化dp
数组用于存储从每个位置出发的最长滑道长度。初始化dx
和dy
数组表示四个可能的移动方向。 - 定义
dfs(x, y)
函数,该函数返回从位置(x, y)
开始的最长滑道长度。 - 如果 dp[x][y] 不为0,说明已经计算过,直接返回。否则,初始化 dp[x][y] 为1(即当前位置至少构成长度为1的滑道)。
- 尝试向四个方向移动,如果新位置 (nx, ny) 的高度低于当前位置,则递归调用 dfs(nx, ny) 并更新 dp[x][y]。
- 遍历所有位置,调用
dfs
函数并更新答案ans
。最后输出答案ans。
时间和空间复杂度:时间复杂度为 O(n * m * 4),简化后为 O(n * m);空间复杂度为 O(n * m)。
#include <iostream> using namespace std; // 定义常量,表示矩阵的最大尺寸 const int MAXN = 1e2 + 2; // 定义四个方向的移动向量 int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1}; int n, m; int mat[MAXN][MAXN]; int dp[MAXN][MAXN] = {0}; // 动态规划数组,存储从每个点出发的最大递增路径长度 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], ny = y + dy[i]; // 检查新坐标是否在矩阵范围内,且高度是否递减 if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue; if (mat[nx][ny] <= mat[x][y]) continue; // 递归调用,更新从 (x, y) 出发的最大路径长度 dp[x][y] = max(dp[x][y], dfs(nx, ny) + 1); } return dp[x][y]; } int main() { cin >> n >> m; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> mat[i][j]; int ans = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) ans = max(ans, dfs(i, j)); // 计算从每个点出发的最大递增路径长度,并更新最终答案 cout << ans << endl; return 0; }