题目链接:https://www.acwing.com/problem/content/description/277/
确定步数和横坐标以后,纵坐标是可以计算出来的,
所以设 (dp[i][j][k]) 表示走了 (i) 步,横坐标分别为 (j, k) 时的最大值,
转移时注意将走到同一格子的情况排除
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int n, m;
int a[55][55], dp[110][55][55];
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
n = read(), m = read();
for(int i = 1 ; i <= n ; ++i){
for(int j = 1 ; j <= m ; ++j){
a[i][j] = read();
}
}
dp[2][1][1] = 0;
for(int i = 3 ; i <= n + m ; ++i){
for(int j = 1 ; j <= min(n, i) ; ++j){
for(int k = 1 ; k <= min(n, i) ; ++k){
if(j == k && i != n + m) continue;
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k - 1] + a[j][i - j] + a[k][i - k]);
if(j - 1 != k || i - 1 == 2) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k] + a[j][i - j] + a[k][i - k]);
if(j != k - 1 || i - 1 == 2) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1] + a[j][i - j] + a[k][i - k]);
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k] + a[j][i - j] + a[k][i - k]);
}
}
}
printf("%d
", dp[n + m][n][n]);
return 0;
}