英语不好,比赛时没看懂题。
题目连接:http://codeforces.com/problemset/problem/429/B
题意:两个人a,b。a只能从点f(1,1)出发前往f(n,m),只能向右或向下走,b从f(n,1)出发前往f(1,m),只能向上或向右走。且他们走过的轨迹只能有一个交点。
分析:
1.因为只能有一个交点,所以对于某一点f(i,j)来说,只存在两种情况,一种是
- (1)a从f(i-1,j)进入f(i,j)走向f(i+1,j),
- (2)b从f(i,j-1)进入f(i,j)走向f(i,j+1)。
另一种是:
- (3)a从f(i,j-1)进入f(i,j)走向f(i,j+1)。
- (4)b从f(i+1,j)进入f(i,j)走向f(i-1,j)。
2.首先看看边界,显然的,边界不可能为a,b路径轨迹的交点,其它点均可。
枚举所有可能为a,b路径轨迹交点的点,找出最大的得分情况。
考虑用六个数组,
- dist1[i][j]储存a从f(1,1)出发,通过方式(1)到达f(i,j)
- dist2[i][j]储存b从f(n,1)出发,通过方式(2)到达f(i,j)
- dist3[i][j]储存a从f(1,1)出发,通过方式(3)到达f(i,j)
- dist4[i][j]储存a从f(n,1)出发,通过方式(4)到达f(i,j)
- dp1[i][j]存储f[i,j)到达点f(n,m)的值。
- dp2[i][j]存储f(i,j)到达点f(1,m)的值。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1005;
int dp1[N][N],dp2[N][N],dist1[N][N],dist2[N][N],dist3[N][N],dist4[N][N];
int map[N][N];
int n,m;
int max(int n,int m)
{
if(n<0)
return m;
else if(m<0)
return n;
else
return n>m?n:m;
}
void init()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
{
dp1[i][j]=0;
dp2[i][j]=0;
dist1[i][j]=0;
dist2[i][j]=0;
dist3[i][j]=0;
dist4[i][j]=0;
}
dp1[n][m]=map[n][m];
dp2[1][m]=map[1][m];
dist1[1][1]=dist3[1][1]=map[1][1];
dist2[n][1]=dist4[n][1]=map[n][1];
}
void DP()
{
for(int i=n;i>0;i--)
{
for(int j=m;j>0;j--)
{
if(i==n&&j==m)
continue;
else if(j==m)
dp1[i][j]=dp1[i+1][j]+map[i][j];
else if(i==n)
dp1[i][j]=dp1[i][j+1]+map[i][j];
else
dp1[i][j]=max(dp1[i][j+1],dp1[i+1][j])+map[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=m;j>0;j--)
{
if(i==1&&j==m)
continue;
else if(j==m)
dp2[i][j]=dp2[i-1][j]+map[i][j];
else if(i==n)
dp2[i][j]=dp2[i][j+1]+map[i][j];
else
dp2[i][j]=max(dp2[i][j+1],dp2[i-1][j])+map[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i==1&&j==1)
continue;
else if(j==1)
dist1[i][j]=dist1[i-1][j]+map[i][j],dist3[i][j]=-1;
else if(i==1)
dist1[i][j]=-1, dist3[i][j]=dist3[i][j-1]+map[i][j];
else
{
dist1[i][j]=max(dist1[i-1][j],dist3[i-1][j])+map[i][j];
dist3[i][j]=max(dist3[i][j-1],dist1[i][j-1])+map[i][j];
}
}
}
for(int i=n;i>0;i--)
{
for(int j=1;j<=m;j++)
{
if(i==n&&j==1)
continue;
else if(j==1)
dist4[i][j]=dist4[i+1][j]+map[i][j],dist2[i][j]=-1;
else if(i==1)
dist4[i][j]=-1, dist2[i][j]=dist2[i][j-1]+map[i][j];
else
{
dist4[i][j]=max(dist4[i+1][j],dist2[i+1][j])+map[i][j];
dist2[i][j]=max(dist2[i][j-1],dist4[i][j-1])+map[i][j];
}
}
}
}
int solve()
{
int minv=0;
int score;
for(int i=2;i<=n-1;i++)
{
for(int j=2;j<=m-1;j++)
{
score=max(dist1[i][j]+dist2[i][j]+dp1[i+1][j]+dp2[i][j+1],dist3[i][j]+dist4[i][j]+dp1[i][j+1]+dp2[i-1][j])-2*map[i][j];
minv=max(score,minv);
}
}
return minv;
}
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
}
}
init();
DP();
cout<<solve()<<endl;
}
return 0;
}