分析
考虑每个格子((i,j))获得的得分即为经过这个格子与不经过这个格子的答案
预处理出起点到每个点的最小得分和每个点到终点的最小得分,
那么经过这个格子的答案很好求,问题是不经过这个格子的答案,
也就是((1,1)->(i-x,j)->(i-x,j+1)->(n,m))或者是
((1,1)->(i,j-x)->(i+1,j-x)->(n,m)),这都是很好求的
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=2011; typedef long long lll;
int n,m,a[N][N]; lll ans,f1[N][N],f2[N][N],dp1[N][N],dp2[N][N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline lll min(lll a,lll b){return a<b?a:b;}
inline lll max(lll a,lll b){return a>b?a:b;}
signed main(){
n=iut(),m=iut(),ans=1e18;
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=m;++j)
a[i][j]=iut();
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=m;++j)
f1[i][j]=max(f1[i][j-1],f1[i-1][j])+a[i][j];
for (rr int i=n;i>=1;--i)
for (rr int j=m;j>=1;--j)
f2[i][j]=max(f2[i][j+1],f2[i+1][j])+a[i][j];
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=m;++j)
dp1[i][j]=max(dp1[i][j-1],f1[i][j]+f2[i+1][j]);
for (rr int j=1;j<=m;++j)
for (rr int i=1;i<=n;++i)
dp2[i][j]=max(dp2[i-1][j],f1[i][j]+f2[i][j+1]);
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=m;++j)
ans=min(ans,max(f1[i][j]+f2[i][j]-2*a[i][j],max(dp1[i][j-1],dp2[i-1][j])));
return !printf("%lld",ans);
}