参考:http://blog.csdn.net/cc_again/article/details/25691925
原题:http://codeforces.com/problemset/problem/429/B
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define LL long long
using namespace std;
//先求出每个点到四个顶点能获得的最大数值
//枚举两者能相遇的点和进出方式,得到最大值,由于有方向限制,所以只有两种进出方式
int a[1010][1010];
LL dp[5][1010][1010];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d",&a[i][j]);
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i++)
{
//cout<<1<<endl;
for(int j = 1; j <= m; j++)
{
dp[1][i][j] = max(dp[1][i-1][j],dp[1][i][j-1])+a[i][j];
// printf(" i:%d j:%d %lld\n",i,j,dp[1][i][j]);
}
// cout<<2<<endl;
for(int j = m; j >= 1; j--)
{
dp[2][i][j] = max(dp[2][i-1][j],dp[2][i][j+1])+a[i][j];
//printf(" i:%d j:%d %lld\n",i,j,dp[1][i][j]);
}
}
for(int i = n; i >= 1; i--)
{
for(int j = 1; j <= m; j++)
dp[3][i][j] = max(dp[3][i+1][j],dp[3][i][j-1])+a[i][j];
for(int j = m; j >= 1; j--)
dp[4][i][j] = max(dp[4][i+1][j],dp[4][i][j+1])+a[i][j];
}
for(int i = 0; i <= n+1; i++)
for(int j = 1; j <= 4; j++)
{
dp[j][i][0] = -inf;
dp[j][i][m+1] = -inf;
}
for(int i = 0; i <= m+1; i++)
for(int j = 1; j <= 4; j++)
{
dp[j][0][i] = -inf;
dp[j][n+1][i] = -inf;
}
LL ans = -inf;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
ans = max(ans,dp[1][i-1][j]+dp[2][i][j+1]+dp[3][i][j-1]+dp[4][i+1][j]);
ans = max(ans,dp[1][i][j-1]+dp[2][i-1][j]+dp[3][i+1][j]+dp[4][i][j+1]);
}
printf("%lld\n",ans);
return 0;
}