有一款双人游戏,游戏的地图是一张 n×m 的平面,其中玩家 A 从地图的左上角出发,通过向右和向下走的方式走到右下角,玩家 B 从右上角出发,通过向左和向下的方式走到左下角(每次只能走到上下左右相邻的至多四个格子)。
每个格子有一个分数,玩家走到格子上就会获得这个分数,当一个玩家得到这个分数后,格子的分数就会自动变为 0。游戏最后的得分是两个人获得分数的总和。
即使两个人同时进入一个格子,这个格子上的分数也只会被计入一次。
现在希望你帮忙计算出,这个游戏能获得的最高分是多少。
输入格式
输入第一行一个整数 T。表示测试数据组数。
接下来输入 T 组数据。每组数据按照下面的规则输入。
对于每组数据第一行输入两个整数 n,m,代表游戏地图的长和宽。
然后接下来的 n 行每行输入 m 个整数,代表地图上每个格子的分数。
1≤T≤15,3≤n,m≤1000。
每个格子分数绝对值 ≤1000。
输出格式
对于第i
组数据,输出格式形如"Case #i: x"
(输出不含引号),其中x
表示该组数据对应的游戏最高分。
样例输入
2 3 4 3 2 2 3 2 2 3 2 1 1 1 1 3 3 -1 -1 -1 -1 -1 -1 -1 -1 -1
样例输出
Case #1: 22 Case #2: -7
#include<bits/stdc++.h> using namespace std; const int MAX=1e3+10; const double PI=acos(-1.0); typedef long long ll; int a[MAX][MAX]; int lu[MAX][MAX];//记录从左上角出发到达(i,j)的最优值 int ld[MAX][MAX];//记录从左下角出发到达(i,j)的最优值 int ru[MAX][MAX];//记录从右上角出发到达(i,j)的最优值 int rd[MAX][MAX];//记录从右下角出发到达(i,j)的最优值 int L[MAX][MAX];//记录以(i,j)为公共横线的左端点的路径的最优值 int D[MAX][MAX];//记录以(i,j)为公共竖线的上端点的路径的最优值 int n,m; void show(int p[][1010]) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++)printf("%d ",p[i][j]);cout<<endl; } cout<<endl; } int main() { int T,cas=1; cin>>T; while(T--) { scanf("%d%d",&n,&m); memset(lu,0,sizeof lu); memset(ru,0,sizeof ru); memset(rd,0,sizeof rd); memset(ld,0,sizeof ld); memset(L,0,sizeof L); memset(D,0,sizeof D); memset(a,0,sizeof a); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++)scanf("%d",&a[i][j]); } for(int i=1;i<=n;i++) //预处理lu[i][j] { for(int j=1;j<=m;j++) { lu[i][j]=-1e9; if(i==1&&j==1)lu[i][j]=a[i][j]; if(i>1)lu[i][j]=max(lu[i][j],lu[i-1][j]+a[i][j]); if(j>1)lu[i][j]=max(lu[i][j],lu[i][j-1]+a[i][j]); } } for(int i=n;i>=1;i--) //预处理ld[i][j] { for(int j=1;j<=m;j++) { ld[i][j]=-1e9; if(i==n&&j==1)ld[i][j]=a[i][j]; if(i<n)ld[i][j]=max(ld[i][j],ld[i+1][j]+a[i][j]); if(j>1)ld[i][j]=max(ld[i][j],ld[i][j-1]+a[i][j]); } } for(int i=1;i<=n;i++) //预处理ru[i][j] { for(int j=m;j>=1;j--) { ru[i][j]=-1e9; if(i==1&&j==m)ru[i][j]=a[i][j]; if(i>1)ru[i][j]=max(ru[i][j],ru[i-1][j]+a[i][j]); if(j<m)ru[i][j]=max(ru[i][j],ru[i][j+1]+a[i][j]); } } for(int i=n;i>=1;i--) //预处理rd[i][j] { for(int j=m;j>=1;j--) { rd[i][j]=-1e9; if(i==n&&j==m)rd[i][j]=a[i][j]; if(i<n)rd[i][j]=max(rd[i][j],rd[i+1][j]+a[i][j]); if(j<m)rd[i][j]=max(rd[i][j],rd[i][j+1]+a[i][j]); } } for(int i=1;i<=n;i++) //预处理L[i][j] { for(int j=m;j>=1;j--) { if(j==m)L[i][j]=rd[i+1][j]+ru[i-1][j]+a[i][j]; else { L[i][j]=L[i][j+1]+a[i][j]; if(i>1&&i<n) { L[i][j]=max(L[i][j],ru[i-1][j]+max(rd[i+1][j],rd[i][j+1])+a[i][j]); L[i][j]=max(L[i][j],rd[i+1][j]+max(ru[i-1][j],ru[i][j+1])+a[i][j]); } else if(i>1&&i==n)L[i][j]=max(L[i][j],ru[i-1][j]+rd[i][j+1]+a[i][j]); else if(i==1&&i<n)L[i][j]=max(L[i][j],ru[i][j+1]+rd[i+1][j]+a[i][j]); } } } for(int j=1;j<=m;j++) //预处理D[i][j] { for(int i=n;i>=1;i--) { if(i==n)D[i][j]=ld[i][j-1]+rd[i][j+1]+a[i][j]; else { D[i][j]=D[i+1][j]+a[i][j]; if(j>1&&j<m) { D[i][j]=max(D[i][j],ld[i][j-1]+max(rd[i][j+1],rd[i+1][j])+a[i][j]); D[i][j]=max(D[i][j],rd[i][j+1]+max(ld[i][j-1],ld[i+1][j])+a[i][j]); } else if(j>1&&j==m)D[i][j]=max(D[i][j],ld[i][j-1]+rd[i+1][j]+a[i][j]); else if(j==1&&j<m)D[i][j]=max(D[i][j],rd[i][j+1]+ld[i+1][j]+a[i][j]); } } } int ans=-1e9; for(int i=1;i<=n;i++) //枚举横线左端点并更新答案 { for(int j=1;j<m;j++) { if(j==1)ans=max(ans,max(lu[i-1][j]+ld[i][j],lu[i][j]+ld[i+1][j])+L[i][j+1]); else { if(i>1&&i<n) { ans=max(ans,ld[i+1][j]+lu[i][j]+L[i][j+1]); ans=max(ans,lu[i-1][j]+ld[i][j]+L[i][j+1]); } else if(i>1&&i==n)ans=max(ans,ld[i][j]+lu[i-1][j]+L[i][j+1]); else if(i==1&&i<n)ans=max(ans,ld[i+1][j]+lu[i][j]+L[i][j+1]); } } } for(int j=1;j<=m;j++) //枚举竖线上端点并更新答案 { for(int i=1;i<n;i++) { if(i==1)ans=max(ans,max(lu[i][j-1]+ru[i][j],lu[i][j]+ru[i][j+1])+D[i+1][j]); else { if(j>1&&j<m) { ans=max(ans,lu[i][j-1]+ru[i][j]+D[i+1][j]); ans=max(ans,ru[i][j+1]+lu[i][j]+D[i+1][j]); } else if(j>1&&j==m)ans=max(ans,lu[i][j-1]+ru[i][j]+D[i+1][j]); else if(j==1&&j<m)ans=max(ans,lu[i][j]+ru[i][j+1]+D[i+1][j]); } } } for(int i=2;i<n;i++) //枚举只有一个公共交点时的答案 { for(int j=2;j<m;j++) { ans=max(ans,lu[i][j-1]+ld[i+1][j]+ru[i-1][j]+rd[i][j+1]+a[i][j]); ans=max(ans,lu[i-1][j]+ld[i][j-1]+ru[i][j+1]+rd[i+1][j]+a[i][j]); } } printf("Case #%d: %d\n",cas++,ans); } return 0; }