1 条题解
-
0
双路径问题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
- 上传者