分析
一个节点到左上,右上,左下,右下的最大值路径是确定的。那么我们考虑见面的点是哪个点。因为见面点是不能计算贡献的,所以我们考虑第一个人和第二个人是分别从哪个方向来的。经过讨论也只有两种可能。
枚举每一个点算出值就可以了。时间复杂度为 。
代码
#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; }