题目大意
给定一个NxM的矩阵,要求从这个矩阵种选出3个边长为K的不重叠的子方阵,使得这三个方阵内所有数的和最大,输出这个最大的和。
N,M,K<=1500
题解
取三个方阵只有这六种情况,前缀和维护下就好了,时间复杂度是O(N^2)的。
Code
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 int Data[1503][1503]; 8 int A[1503][1503],B[1503][1503],C[1503][1503],D[1503][1503]; 9 int AA[1503][1503],BB[1503][1503],CC[1503][1503],DD[1503][1503]; 10 int MaxU[1503],MaxD[1503],MaxL[1503],MaxR[1503]; 11 int N,M,K; 12 13 int main(){ 14 scanf("%d%d%d",&N,&M,&K); 15 for(register int i=1;i<=N;++i) 16 for(register int j=1;j<=M;++j) 17 scanf("%d",&Data[i][j]); 18 for(register int i=1;i<=N;++i){ 19 for(register int j=1;j<=M;++j){ 20 A[i][j]=A[i-1][j]+A[i][j-1]-A[i-1][j-1]+Data[i][j]; 21 B[N-i+1][j]=B[N-i+2][j]+B[N-i+1][j-1]-B[N-i+2][j-1]+Data[N-i+1][j]; 22 C[N-i+1][M-j+1]=C[N-i+2][M-j+1]+C[N-i+1][M-j+2]-C[N-i+2][M-j+2]+Data[N-i+1][M-j+1]; 23 D[i][M-j+1]=D[i][M-j+2]+D[i-1][M-j+1]-D[i-1][M-j+2]+Data[i][M-j+1]; 24 } 25 } 26 for(register int i=1;i<=N;++i){ 27 for(register int j=1;j<=M;++j){ 28 if(i-K>=0 && j-K>=0) AA[i][j]=A[i][j]-A[i-K][j]-A[i][j-K]+A[i-K][j-K]; 29 if(i+K<=N+1 && j-K>=0) BB[i][j]=B[i][j]-B[i+K][j]-B[i][j-K]+B[i+K][j-K]; 30 if(i+K<=N+1 && j+K<=M+1) CC[i][j]=C[i][j]-C[i+K][j]-C[i][j+K]+C[i+K][j+K]; 31 if(i-K>=0 && j+K<=M+1) DD[i][j]=D[i][j]-D[i-K][j]-D[i][j+K]+D[i-K][j+K]; 32 } 33 } 34 for(register int i=1;i<=N;++i){ 35 MaxU[i]=MaxU[i-1]; 36 MaxD[N-i+1]=MaxD[N-i+2]; 37 for(register int j=1;j<=M;++j){ 38 MaxU[i]=max(MaxU[i],AA[i][j]); 39 MaxD[N-i+1]=max(MaxD[N-i+1],BB[N-i+1][j]); 40 } 41 } 42 for(register int i=1;i<=M;++i){ 43 MaxL[i]=MaxL[i-1]; 44 MaxR[M-i+1]=MaxR[M-i+2]; 45 for(register int j=1;j<=N;++j){ 46 MaxL[i]=max(MaxL[i],AA[j][i]); 47 MaxR[M-i+1]=max(MaxR[M-i+1],CC[j][M-i+1]); 48 } 49 } 50 int Ans=0; 51 for(register int i=2*K;i<=N-K;++i)//Case1 52 for(register int j=1;j<=M;++j) 53 Ans=max(Ans,AA[i][j]+MaxU[i-K]+MaxD[i+1]); 54 for(register int i=2*K;i<=M-K;++i)//Case2 55 for(register int j=1;j<=N;++j) 56 Ans=max(Ans,AA[j][i]+MaxL[i-K]+MaxR[i+1]); 57 for(register int i=1;i<=N;++i){ 58 for(register int j=1;j<=M;++j){ 59 AA[i][j]=max(AA[i][j],max(AA[i-1][j],AA[i][j-1])); 60 BB[N-i+1][j]=max(BB[N-i+1][j],max(BB[N-i+2][j],BB[N-i+1][j-1])); 61 CC[N-i+1][M-j+1]=max(CC[N-i+1][M-j+1],max(CC[N-i+2][M-j+1],CC[N-i+1][M-j+2])); 62 DD[i][M-j+1]=max(DD[i][M-j+1],max(DD[i][M-j+2],DD[i-1][M-j+1])); 63 } 64 } 65 for(register int i=1;i<=N;++i){ 66 for(register int j=K;j<=M-K;++j){ 67 if(i>=K) Ans=max(Ans,MaxU[i]+BB[i+1][j]+CC[i+1][j+1]); 68 if(i+K-1<=N) Ans=max(Ans,MaxD[i]+AA[i-1][j]+DD[i-1][j+1]); 69 } 70 } 71 for(register int i=1;i<=M;++i){ 72 for(register int j=K;j<=N-K;++j){ 73 if(i>=K) Ans=max(Ans,MaxL[i]+DD[j][i+1]+CC[j+1][i+1]); 74 if(i+K-1<=M)Ans=max(Ans,MaxR[i]+AA[j][i-1]+BB[j+1][i-1]); 75 } 76 } 77 cout<<Ans<<endl; 78 79 return 0; 80 }