当前位置:首页 > 比赛题解 > 2020年CSP-J 方格取数问题详解:双向动态规划解法与路径优化策略

2020年CSP-J 方格取数问题详解:双向动态规划解法与路径优化策略

6小时前比赛题解22

截图未命名.jpg 2020年CSP-J 方格取数问题详解:双向动态规划解法与路径优化策略 CSP-J竞赛 动态规划 路径优化 双向处理 网格遍历 第1张

一、问题背景与需求分析

题目要求在一个n×m的方格矩阵中,从左上角(0,0)出发到右下角(n-1,m-1),每次可以向右、向上或向下移动,找出路径上数字之和最大的路线。

核心难点

  1. 路径方向多样性(右、上、下)

  2. 避免路径交叉和循环

  3. 需要考虑来自不同方向的最优解

二、完整代码实现(带详细注释)

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

const int INF = 1e9;  // 定义无穷大值

int main() {
    ios::sync_with_stdio(false);  // 关闭同步提升IO速度
    cin.tie(nullptr);             // 解除cin与cout的绑定
    
    int n, m;
    cin >> n >> m;
    
    // 读取网格数据
    vector<vector<int>> grid(n, vector<int>(m));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> grid[i][j];
        }
    }
    
    // 三维DP数组:dp[i][j][0]表示从上方到达(i,j)的最大和
    // dp[i][j][1]表示从下方到达(i,j)的最大和
    vector<vector<vector<long long>>> dp(n, vector<vector<long long>>(m, vector<long long>(2, -INF)));
    
    // 初始化起点
    dp[0][0][0] = dp[0][0][1] = grid[0][0];
    
    // 处理第一列(只能从上到下)
    for (int i = 1; i < n; ++i) {
        dp[i][0][0] = dp[i][0][1] = dp[i-1][0][0] + grid[i][0];
    }
    
    // 动态规划处理(按列处理)
    for (int j = 1; j < m; ++j) {
        // 从上到下处理当前列
        for (int i = 0; i < n; ++i) {
            if (i == 0) {  // 第一行只能从左边来
                dp[i][j][0] = max(dp[i][j-1][0], dp[i][j-1][1]) + grid[i][j];
            } else {  // 可以从左边或上方来
                dp[i][j][0] = max({dp[i][j-1][0], dp[i][j-1][1], dp[i-1][j][0]}) + grid[i][j];
            }
        }
        
        // 从下到上处理当前列
        for (int i = n-1; i >= 0; --i) {
            if (i == n-1) {  // 最后一行只能从左边来
                dp[i][j][1] = max(dp[i][j-1][0], dp[i][j-1][1]) + grid[i][j];
            } else {  // 可以从左边或下方来
                dp[i][j][1] = max({dp[i][j-1][0], dp[i][j-1][1], dp[i+1][j][1]}) + grid[i][j];
            }
        }
    }
    
    // 输出结果(取两种方向中的最大值)
    cout << max(dp[n-1][m-1][0], dp[n-1][m-1][1]) << endl;
    
    return 0;
}

三、算法核心思想解析

  1. 三维DP设计

    • 第三维[0]/[1]分别表示从上/从下到达该点

    • 避免路径方向冲突

  2. 双向处理策略

    • 每列先从上到下计算(考虑来自左和上的路径)

    • 再从下到上计算(考虑来自左和下的路径)

  3. 边界处理

    • 第一列只能垂直移动

    • 第一行和最后一行有特殊处理

四、复杂度分析与优化

  1. 时间复杂度:O(n×m) 每个格子处理两次

  2. 空间优化:可降维到O(n)只存储前一列数据

  3. 实际应用:可扩展到三维路径规划问题

五、常见错误与调试技巧

  1. 初始化问题:忘记初始化起点

  2. 方向混淆:上下方向处理错误

  3. 边界条件:行列边界处理不当

  4. 调试建议:打印每步DP值验证


原创内容 转载请注明出处

分享给朋友:

发表评论

访客

看不清,换一张

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