标签:class using 维护 ret hide 情况 mem clu name
考虑将三个矩形按某种方式划分为再三个大矩形中找最大值,容易发现只有6种划分方式,分为两类:
1.4种,考虑第一条横/竖和第二条在第一条的两侧,这一类情况只需要预处理出左上/左下/右上/右下的最大子矩阵即可
2.2种,两条横线/竖线划分,以横线为例,只需要处理处每一行的答案,然后,然后简单维护一下即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 2005 4 int n,m,k,x,y,ans,f[N],a[N][N],ll[N][N],lr[N][N],rl[N][N],rr[N][N]; 5 int S(int x,int y){ 6 return a[x][y]-a[x-k][y]-a[x][y-k]+a[x-k][y-k]; 7 } 8 int main(){ 9 scanf("%d%d%d",&n,&m,&k); 10 for(int i=1;i<=n;i++) 11 for(int j=1;j<=m;j++){ 12 scanf("%d",&x); 13 a[i][j]=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+x; 14 } 15 for(int i=k;i<=n;i++) 16 for(int j=k;j<=m;j++) 17 ll[i][j]=max(max(ll[i][j-1],ll[i-1][j]),S(i,j)); 18 for(int i=k;i<=n;i++) 19 for(int j=m-k+1;j;j--) 20 lr[i][j]=max(max(lr[i][j+1],lr[i-1][j]),S(i,j+k-1)); 21 for(int i=n-k+1;i;i--) 22 for(int j=k;j<=m;j++) 23 rl[i][j]=max(max(rl[i][j-1],rl[i+1][j]),S(i+k-1,j)); 24 for(int i=n-k+1;i;i--) 25 for(int j=m-k+1;j;j--) 26 rr[i][j]=max(max(rr[i][j+1],rr[i+1][j]),S(i+k-1,j+k-1)); 27 for(int i=k;i<=n-k;i++) 28 for(int j=k;j<=m-k;j++){ 29 ans=max(ans,ll[n][j]+lr[i][j+1]+rr[i+1][j+1]); 30 ans=max(ans,ll[i][j]+lr[i][j+1]+rr[i+1][1]); 31 ans=max(ans,ll[i][m]+rl[i+1][j]+rr[i+1][j+1]); 32 ans=max(ans,ll[i][j]+rl[i+1][j]+rr[1][j+1]); 33 } 34 for(int i=k;i<=n;i++) 35 for(int j=k;j<=m;j++)f[i]=max(f[i],S(i,j)); 36 x=0; 37 for(int i=k;i<=n;i++){ 38 x=max(x,f[i]); 39 int y=0; 40 for(int j=i+k;j<=n-k;j++){ 41 y=max(y,f[j]); 42 ans=max(ans,x+y+rr[j+1][1]); 43 } 44 } 45 x=0; 46 memset(f,0,sizeof(f)); 47 for(int i=k;i<=n;i++) 48 for(int j=k;j<=m;j++)f[j]=max(f[j],S(i,j)); 49 for(int i=k;i<=m;i++){ 50 x=max(x,f[i]); 51 int y=0; 52 for(int j=i+k;j<=m-k;j++){ 53 y=max(y,f[j]); 54 ans=max(ans,x+y+rr[1][j+1]); 55 } 56 } 57 printf("%d",ans); 58 }
标签:class using 维护 ret hide 情况 mem clu name
原文地址:https://www.cnblogs.com/PYWBKTDA/p/12121549.html