题目链接:
http://codeforces.com/problemset/problem/429/B
题目意思:
给n*m的矩阵,每个格子有个数,A从(1,1)出发只能向下或右走,终点为(n,m),B从(n,1)出发只能向上或右走,终点为(1,m)。两个人的速度不一样,走到的格子可以获的该格子的数,两人相遇的格子上的数两个人都不能拿。求A和B能拿到的数的总和的最大值。
n,m<=1000
解题思路:
dp.
先预处理出每个格子到四个角落格子的路径最大数值,然后枚举两个人相遇的交点格子,枚举A、B的进来和出去方式,求最大值即可。
注意边界情况。
代码:
//#include<CSpreadSheet.h>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 1100
ll dp[5][Maxn][Maxn];
int n,m;
ll save[Maxn][Maxn];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(~scanf("%d%d",&n,&m))
{
memset(save,0,sizeof(save));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&save[i][j]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
dp[1][i][j]=max(dp[1][i-1][j],dp[1][i][j-1])+save[i][j];
//printf("i:%d j:%d %I64d\n",i,j,dp[1][i][j]);
for(int j=m;j>=1;j--)
dp[3][i][j]=max(dp[3][i-1][j],dp[3][i][j+1])+save[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])+save[i][j];
for(int j=m;j>=1;j--)
dp[4][i][j]=max(dp[4][i+1][j],dp[4][i][j+1])+save[i][j];
}
ll ans=0;
for(int i=0;i<=n+1;i++) //把四个边界都置为无效情况
for(int k=1;k<=4;k++)
dp[k][i][0]=dp[k][i][m+1]=-INF;
for(int j=0;j<=m+1;j++)
for(int k=1;k<=4;k++)
dp[k][0][j]=dp[k][n+1][j]=-INF;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{ //只用考虑两种情况 两个人只能交叉一个格子,多了的话不合算
ll temp=dp[1][i][j-1]+dp[4][i][j+1]+dp[2][i+1][j]+dp[3][i-1][j];
ans=max(ans,temp);
temp=dp[1][i-1][j]+dp[4][i+1][j]+dp[2][i][j-1]+dp[3][i][j+1];
ans=max(ans,temp);
//printf("i:%d j:%d %I64d\n",i,j,ans);
}
}
printf("%I64d\n",ans);
}
return 0;
}