[BZOJ 1177][APIO 2009] Oil 采油区域

题目大意

给定一个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 }
posted @ 2020-01-14 20:32  AE酱  阅读(199)  评论(0编辑  收藏  举报