1 条题解

  • 0
    @ 2025-10-10 9:04:00

    双路径问题dp需要使用三维数组,分别为走过的步数,第一条走到的所在行,第二条走到的所在行。

    dp数组不用记录走到的所在列,因为用步数减去所在行就可以得到列的位置

    完整代码如下,详细看注释

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    int main() 
    {
        int n, m, i, j, k;
        // 读取森林的行数n和列数m
        cin >> n >> m;
        
        // 创建n×m的矩阵来存储每个位置的蘑菇数量
        vector<vector<int>> map(n, vector<int>(m));
        for (i = 0; i < n; i++) 
    	{
            for (j = 0; j < m; j++) 
    		{
                cin >> map[i][j]; // 读取每个位置的蘑菇数量
            }
        }
    
        // 计算从起点(0,0)到终点(n-1,m-1)需要走的步数
        // 因为只能向右或向下,所以总步数为(n-1)+(m-1)+1 = n+m-1
        int steps = n + m - 1;
        
        // 创建三维动态规划数组f[i][j][k]
        // i: 当前已经走的步数(从0到steps-1)
        // j: 第一条路径当前所在的行
        // k: 第二条路径当前所在的行
        // 值f[i][j][k]表示走到这一步时,两条路径采集到的蘑菇总数
        vector<vector<vector<int>>> f(steps, vector<vector<int>>(n, vector<int>(n, -1)));
        
        // 初始化起点(0,0)的状态
        // 两条路径都从起点出发,所以只计算一次起点的蘑菇数量
        f[0][0][0] = map[0][0];
    
        // 动态规划:遍历所有可能的步数(从第1步到第steps-1步)
        for (i = 1; i < steps; i++) 
    	{
            // 遍历所有可能的第一条路径所在行
            for (j = 0; j < n; j++) 
    		{
                // 遍历所有可能的第二条路径所在行
                for (k = 0; k < n; k++) 
    			{
                    // 计算第一条路径在当前步数i和行j时的列位置
                    int j1 = i - j;
                    // 计算第二条路径在当前步数i和行k时的列位置
                    int j2 = i - k;
                    
                    // 检查列坐标是否合法(在0到m-1范围内)
                    if (j1 < 0 || j1 >= m || j2 < 0 || j2 >= m) continue;
                    
                    // 检查两条路径是否走到了同一个位置(除了起点和终点)
                    // 如果走到了同一个位置,且不是终点,则跳过(因为同一个位置的蘑菇只能采一次)
                    if (j == k && i != steps - 1) continue;
                    
                    // 计算当前两个位置采集的蘑菇总数
                    int current = map[j][j1] + map[k][j2];
                    // 如果两条路径走到了同一个位置(只会在起点或终点发生),则只计算一次蘑菇数量
                    if (j == k) current = map[j][j1];
                    
                    // 初始化前一步的最大蘑菇数为-1(表示不可达)
                    int max_prev = -1;
                    
                    // 情况1: 两条路径都从上方向下走到达当前位置
                    // 检查第一条路径是否可以从上方下来(j>0),第二条路径是否可以从上方下来(k>0)
                    if (j > 0 && k > 0) 
                        max_prev = max(max_prev, f[i-1][j-1][k-1]);
                    
                    // 情况2: 第一条路径从上方向下走,第二条路径从左方向右走
                    // 检查第一条路径是否可以从上方下来(j>0),第二条路径是否可以从左方过来(j2>0)
                    if (j > 0 && j2 > 0) 
                        max_prev = max(max_prev, f[i-1][j-1][k]);
                    
                    // 情况3: 第一条路径从左方向右走,第二条路径从上方向下走
                    // 检查第一条路径是否可以从左方过来(j1>0),第二条路径是否可以从上方下来(k>0)
                    if (j1 > 0 && k > 0) 
                        max_prev = max(max_prev, f[i-1][j][k-1]);
                    
                    // 情况4: 两条路径都从左方向右走到达当前位置
                    // 检查第一条路径是否可以从左方过来(j1>0),第二条路径是否可以从左方过来(j2>0)
                    if (j1 > 0 && j2 > 0) 
                        max_prev = max(max_prev, f[i-1][j][k]);
                    
                    // 如果前一步有可达的状态,则更新当前状态
                    if (max_prev != -1) {
                        f[i][j][k] = max_prev + current;
                    }
                }
            }
        }
    
        // 输出结果:两条路径到达终点(n-1, m-1)时采集到的蘑菇总数
        cout << f[steps-1][n-1][n-1] << endl;
    
        return 0;
    }
    
    • 1

    信息

    ID
    160
    时间
    2000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者