题目链接 https://www.jisuanke.com/course/709/36579
题解: 这道题想了半天没想到好的方法,看了答案的代码后才恍然大悟。
从左上角和右上角出发最终会形成2条路径,这2条路径肯定是相交的。要使积分和最大,交点肯定只有1个(解此题的关键所在)。
理由: 假设2条路径已经交于1点了,由于一条路只能往右(下)发展,另一条路只能往左(下)发展,所以如果有多个交点的话,这多个交点必定是连续的。然后2条路继续扩张,扩张来达到新的点,即2条路不再相交的地方,这时,对于其中一条路来讲,要达到此时新的一点,既可以走刚才那条有几个交点的路,也可以走交点旁边空白的路再到达此时的点,这样能获得更多积分。(感觉说得不太清楚,只要能理解到只能有1个交点这题就迎刃而解了)
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 550
using namespace std;
int dp1[MAXN][MAXN],dp2[MAXN][MAXN],dp3[MAXN][MAXN],dp4[MAXN][MAXN];
int a[MAXN][MAXN];
int n,m;
int main() {
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++) {
scanf("%d",&a[i][j]);
}
// 朝右下角走
for(int i = n;i >= 1;i--)
for(int j = m;j >= 1;j--) {
dp1[i][j] = a[i][j] + max(dp1[i+1][j],dp1[i][j+1]);
}
// 朝左上角走
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++) {
dp2[i][j] = a[i][j] + max(dp2[i-1][j],dp2[i][j-1]);
}
// 朝左下角走
for(int i = n;i >= 1;i--)
for(int j = 1;j <= m;j++) {
dp3[i][j] = a[i][j] + max(dp3[i+1][j],dp3[i][j-1]);
}
// 朝右上角走
for(int i = 1;i <= n;i++)
for(int j = m;j >= 1;j--) {
dp4[i][j] = a[i][j] + max(dp4[i-1][j],dp4[i][j+1]);
}
int res = 0;
for(int i = 2;i < n;i++)
for(int j = 2;j < m;j++) {
res = max(res,a[i][j] + max(dp2[i-1][j]+dp1[i+1][j]+dp3[i][j-1]+dp4[i][j+1],dp2[i][j-1]
+dp1[i][j+1]+dp3[i+1][j]+dp4[i-1][j]));
}
printf("%d\n",res);
return 0;
}