😊博主目前也在学习,有错误欢迎指正😊
🌈保持热爱 奔赴星海🌈
文章目录
- 一、题目
- 1、题目描述
- 3、原题链接
- 二、解题报告
- 1、思路分析
- 2、代码详解
- 三、本题知识
一、题目
1、题目描述
输入格式:
输入的第一行为一个整数 NN(表示 N \times NN×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 00 表示输入结束。
输出格式:
只需输出一个整数,表示 22 条路径上取得的最大的和。
输入样例:
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
输出样例:
67
3、原题链接
方格取数
二、解题报告
1、思路分析
(1)由题意可知,我们要从A到B走两次。我们用一个数组f[i1][j1][i2][j2]表示从(1,1)走到(i1,j1)(i2,j2)路径的最大值。
(2)我们令k = i1 + j1 = i2 + j2,为什么i1 + j1 = i2 + j2呢,其实i1 + j1 和 i2 + j2表示的就是表示两个点分别在x轴y轴走的距离,也就是走的步数,即k表示走的步数。这样我们就可以用k - i表示j,可以把f数组降为三维,即f[k,i1,i2],他表示从(1,1)走到(i1,k- i1)(i2,k - i2)路径的最大值.
(3)下面我们来分析一下所有可能的情况:
因为两个点(i1,j1)(i2,j2)都有向右和向下两个运动方向,所以一共有四种状态。
- 当两个点都向下运动时,f[k][i1][i2] = max(x,f[k - 1][i1 - 1][i2 - 1] + t)。
- 当第一个点向下另一个店向右时,f[k][i1][i2] = max(x,f[k - 1][i1 - 1][i2] + t)。
- 当第一个点向右另一个店向下时,f[k][i1][i2] = max(x,f[k - 1][i1][i2 - 1] + t)。
- 当两个点都向右运动时,f[k][i1][i2] = max(x,f[k - 1][i1][i2] + t)。
注意:式子中的t表示两个点运动后路径的增加值。
2、代码详解
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20,M = 40;
int n;
int f[M][N][N];//f[k][i1][i2]表示从(1,1)分别走到(i1,k - i1)和(i2,k - i2)的最大和
int w[N][N];
int main() {
cin >> n;
int a,b,c;
while(cin >> a >> b >> c,a || b || c) w[a][b] = c;
for(int k = 2;k <= n + n;k++) {//遍历所有走的步数
for(int i1 = 1;i1 <= n;i1++) {//遍历所有第一个点的情况
for(int i2 = 1;i2 <= n;i2++) {//遍历所有第二个点的情况
int j1 = k - i1,j2 = k - i2;//纵坐标
if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) {
int t = w[i1][j1];
if(i1 != i2) t += w[i2][j2];
int &x = f[k][i1][i2];
x = max(x,f[k - 1][i1 - 1][i2 - 1] + t);//两个点都向下运动
x = max(x,f[k - 1][i1 - 1][i2] + t);//第一个点向下另一个店向右
x = max(x,f[k - 1][i1][i2 - 1] + t);//第一个点向右另一个店向下
x = max(x,f[k - 1][i1][i2] + t);//两个点都向右运动
}
}
}
}
cout << f[n + n][n][n] << endl;
return 0;
}
三、本题知识
动态规划