当前位置:首页 > 牛客 > 牛客233065题:最长滑雪路径的动态规划与记忆化搜索解法

牛客233065题:最长滑雪路径的动态规划与记忆化搜索解法

2个月前 (08-27)

牛客233065题:最长滑雪路径的动态规划与记忆化搜索解法 动态规划 记忆化搜索 深度优先搜索 深搜 DFS 递归 C++ 牛客题解 第1张

一、题目解读

牛客233065题要求求解给定矩阵中的最长滑雪路径。滑雪者从任意点出发,每次只能向高度严格递减的相邻格子移动(上下左右四个方向),需找到路径长度最大值。题目考察动态规划与搜索算法的结合,重点在于优化重复计算以提高效率。

二、解题思路

采用深度优先搜索DFS)结合记忆化技术解决该问题。核心思路如下:

1. 记忆化搜索:为避免重复计算每个点的最长路径,使用二维备忘录记录已求解结果。

2. 递归式设计:从每个点出发递归搜索四周符合条件的低高度点,路径长度为其后继点最长路径+1。

3. 边界条件:严格检查矩阵边界及高度递减要求,确保路径合法性。

通过动态规划的思想,将递归搜索转化为有记忆的优化算法,显著降低时间复杂度。

三、解题步骤

1. 初始化:读取矩阵尺寸,创建与矩阵同大小的备忘录(全0表示未计算)。

2. 外层循环:遍历矩阵每个点作为起点,调用DFS函数更新最长路径结果。

3. DFS函数:

    若当前点已计算,直接返回备忘录值。

    遍历四个方向,对合法相邻点(边界内且高度递减)递归调用DFS,获取其最长路径。

    更新当前点的路径长度为所有后继点路径最大值+1,存入备忘录。

4. 结果汇总:外层循环结束后,备忘录中存储了所有点的最长路径,取全局最大值即为答案。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; // 四个方向

int dfs(vector<vector<int>>& matrix, vector<vector<int>>& memo, int i, int j) {
    if(memo[i][j]!= 0) return memo[i][j]; // 已计算过,直接返回结果
    
    int max_len = 1; // 至少包含自己
    for(auto& dir : dirs) { // 遍历四个方向
        int x = i + dir[0], y = j + dir[1];
        // 边界检查且高度必须严格递减
        if(x >= 0 && x < matrix.size() && y >= 0 && y < matrix[0].size() 
           && matrix[x][y] < matrix[i][j]) {
            max_len = max(max_len, dfs(matrix, memo, x, y) + 1);
        }
    }
    memo[i][j] = max_len; // 记忆化存储当前点的最长路径
    return max_len;
}

int longestSkiPath(vector<vector<int>>& matrix) {
    if(matrix.empty()) return 0;
    int n = matrix.size(), m = matrix[0].size();
    vector<vector<int>> memo(n, vector<int>(m, 0)); // 初始化备忘录
    int res = 0;
    
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            res = max(res, dfs(matrix, memo, i, j)); // 更新全局最长路径
        }
    }
    return res;
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> matrix(n, vector<int>(m));
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            cin >> matrix[i][j];
        }
    }
    cout << longestSkiPath(matrix) << endl;
    return 0;
}

五、总结

该解法巧妙地将动态规划思想融入DFS,通过备忘录消除递归中的重复计算,将时间复杂度优化至O(NM)(N为矩阵行数,M为列数)。代码结构清晰,边界处理严谨,是解决此类路径问题的典型范例。实际应用中,记忆化搜索常作为优化递归算法的有效手段,值得深入掌握。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣451:ASCII数组计数法 用128个桶解决频率排序问题

力扣451:ASCII数组计数法 用128个桶解决频率排序问题

题目重解给定一个字符串,将字符按照出现频率降序排列。例如输入"tree",可能返回"eetr"或"eert"。题目要求我们不考虑字母顺序,只...

力扣740.删除并获得点数 预处理与动态规划的巧妙融合

力扣740.删除并获得点数 预处理与动态规划的巧妙融合

题意解析:给定一组数字,每当你选择一个数字x时,所有等于x-1和x+1的数字都会被自动移除。你需要通过巧妙的选择顺序,最大化获得的点数总和。这个问题可以转化为对离散化数字分布的动态规划问题——将相邻数...

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

一、题目解读    2024年GESP(青少年软件编程能力等级考试)五级中的“武器强化”(洛谷平台题目编号B4071)是一道典型的算法优化问题。题目要求通过合理...

NOIP 2008火柴棒等式题解(C++代码实现)  动态规划与枚举算法详解

NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解

一、题目解读火柴棒等式问题(NOIP 2008,洛谷P1149)要求使用给定数量的火柴棒,构造形如 A + B = C 的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式...

【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解

【CSP-S 2019】括号树(洛谷P5658)解题报告:栈+DFS+异或优化详解

一、题目解读括号树问题(洛谷P5658)要求处理一个由括号序列转化的树结构:每个节点表示一个括号,'('为子节点,')'为父节点。题目给定一棵n个节点的树,需计算每个节...

2017年 NOIP 提高组 逛公园(洛谷P3953)题解:代码解析与优化

2017年 NOIP 提高组 逛公园(洛谷P3953)题解:代码解析与优化

一、题目解读    2017年NOIP提高组“逛公园”题目(洛谷P3953)要求在有向图中计算从起点到终点满足特定条件的路径数量。题目难点在于处理路径长度限制与...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。