分析

一个节点到左上,右上,左下,右下的最大值路径是确定的。那么我们考虑见面的点是哪个点。因为见面点是不能计算贡献的,所以我们考虑第一个人和第二个人是分别从哪个方向来的。经过讨论也只有两种可能。图片说明
枚举每一个点算出值就可以了。时间复杂度为

代码

#include<bits/stdc++.h>
using namespace std;
int read() {
    int x = 0,f = 0;char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = 1;ch = getchar();}
    while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
    return f ? -x : x;
}
const int N = 1010;
int a[N][N],dp[4][N][N],n,m;
int main()
{
    n = read();m = read();
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= m;j++) {
            a[i][j] = read();
        }
    }
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= m;j++)
        dp[0][i][j] = max(dp[0][i][j-1],dp[0][i-1][j]) + a[i][j]; // 左上 
        for(int j = m;j >= 1;j--)
        dp[1][i][j] = max(dp[1][i][j+1],dp[1][i-1][j]) + a[i][j]; // 右上 
    }
    for(int i = n;i >= 1;i--) {
        for(int j = 1;j <= m;j++)
        dp[2][i][j] = max(dp[2][i+1][j],dp[2][i][j-1]) + a[i][j]; // 左下 
        for(int j = m;j >= 1;j--)
        dp[3][i][j] = max(dp[3][i+1][j],dp[3][i][j+1]) + a[i][j]; // 右下 
    }
    int ans = 0;
    for(int i = 2;i < n;i++) {
        for(int j = 2;j < m;j++) {
            ans = max(ans,dp[0][i][j-1]+dp[3][i][j+1]+dp[1][i-1][j]+dp[2][i+1][j]);
            ans = max(ans,dp[0][i-1][j]+dp[3][i+1][j]+dp[1][i][j+1]+dp[2][i][j-1]);
        }
    }
    cout << ans << endl;
    return 0;
}