神仙题
难点在于代码实现
这狗日的题。。。
首先暴力是这样的
枚举三个坐标
这是n^6做法,没什么卵用
但是我们发现把一张图分割成3块那么可以做
但是问题是这是情况多多的
所以成了码农题
#include<bits/stdc++.h>
using namespace std;
const int N=1801;
int sum[N][N]={};
int a[N][N]={};//左上
int b[N][N]={};//右上
int c[N][N]={};//左下
int d[N][N]={};//右下
int ans=-1;
int m,n,k;
int main(){
scanf("%d%d%d",&m,&n,&k);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
int x;
scanf("%d",&x);
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+x;
}
}
for(int i=m;i>=k;i--){
for(int j=n;j>=k;j--){
sum[i][j]=sum[i][j]-sum[i-k][j]-sum[i][j-k]+sum[i-k][j-k];
}
}
//四个角
for(int i=k;i<=m;i++){
for(int j=k;j<=n;j++){
a[i][j]=max(sum[i][j],max(a[i-1][j],a[i][j-1]));
}
} //左上角
for(int i=k;i<=m;i++){
for(int j=n;j>=k;j--){
b[i][j]=max(sum[i][j],max(b[i-1][j],b[i][j+1]));
}
}//右上角
for(int i=m;i>=k;i--){
for(int j=k;j<=n;j++){
c[i][j]=max(sum[i][j],max(c[i+1][j],c[i][j-1]));
}
}//左下角
for(int i=m;i>=k;i--){
for(int j=n;j>=k;j--){
d[i][j]=max(sum[i][j],max(d[i+1][j],d[i][j+1]));
}
}
//第一维枚举横线
//第二维枚举竖线
for(int i=k;i<=m-k;i++){
for(int j=k;j<=n-k;j++){
ans=max(ans,a[i][j]+b[i][j+k]+c[i+k][n]);
}
}
for(int i=k;i<=m-k;i++){
for(int j=k+k;j<=n;j++){
ans=max(ans,b[i][j]+d[i+k][j]+a[n][j-k]);
}
}
for(int i=k+k;i<=m;i++){
for(int j=k;j<=n-k;j++){
ans=max(ans,c[i][j]+d[i][j+k]+a[i-k][n]);
}
}
for(int i=k;i<=n-k;i++){
for(int j=k;j<=m-k;j++){
ans=max(ans,a[i][j]+c[i+k][j]+b[m][j+k]);
}
}
//两条平行线
for(int i=k;i<=n;i++){
for(int j=k+k;j<=m-k;j++){
ans=max(ans,sum[i][j]+a[i][j-k]+b[i][j+k]);
}
}
for(int i=k+k;i<=n-k;i++){
for(int j=k;j<=m;j++){
ans=max(ans,sum[i][j]+a[i-k][n]+c[i+k][n]);
}
}
cout<<ans;
return 0;
}