bzoj 1177: [Apio2009]Oil
神啊!!
3个块有6种情况(网上神犇有图!),然后在6种情况里,分别找分出的3块的最大值就好。(发现可以用DP预处理一下分别以每个点给正方形的左下,左上,右下,右上为端点的最大值,然后处理答案的时候可以直接O(1)查询了)
(代码奇丑)
1 #include <bits/stdc++.h> 2 #define LL long long 3 #define lowbit(x) x&(-x) 4 #define inf 0x3f3f3f3f 5 #define N 2005 6 using namespace std; 7 inline int ra() 8 { 9 int x=0,f=1; char ch=getchar(); 10 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 11 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 12 return x*f; 13 } 14 int n,m,k,s[N][N],a[N][N],b[N][N],c[N][N],d[N][N],ans,t[N][N]; 15 int main(int argc, char const *argv[]) 16 { 17 scanf("%d%d%d",&n,&m,&k); 18 for (int i=1; i<=n; i++) 19 for (int j=1; j<=m; j++) 20 { 21 int x; scanf("%d",&x); 22 s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+x; 23 } 24 for (int i=k; i<=n; i++) 25 for (int j=k; j<=m; j++) 26 t[i][j]=s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k]; 27 for (int i=1; i<=n; i++) 28 for (int j=1; j<=n; j++) 29 s[i][j]=t[i][j]; 30 for (int i=k; i<=n; i++) 31 for (int j=k; j<=m; j++) 32 a[i][j]=max(s[i][j],max(a[i-1][j],a[i][j-1])); 33 for (int i=k; i<=n; i++) 34 for (int j=m-k+1; j>=1; j--) 35 b[i][j]=max(s[i][j+k-1],max(b[i][j+1],b[i-1][j])); 36 for (int i=n-k+1; i>=1; i--) 37 for (int j=k; j<=m; j++) 38 c[i][j]=max(s[i+k-1][j],max(c[i+1][j],c[i][j-1])); 39 for (int i=n-k+1; i>=1; i--) 40 for (int j=m-k+1; j>=1; j--) 41 d[i][j]=max(s[i+k-1][j+k-1],max(d[i+1][j],d[i][j+1])); 42 for (int i=k; i<=n-k; i++) 43 for (int j=k; j<=m-k; j++) 44 { 45 ans=max(ans,a[i][j]+b[i][j+1]+c[i+1][m]); 46 ans=max(ans,a[i][m]+c[i+1][j]+d[i+1][j+1]); 47 ans=max(ans,a[i][j]+d[1][j+1]+c[i+1][j]); 48 ans=max(ans,a[n][j]+b[i][j+1]+d[i+1][j+1]); 49 } 50 for (int i=k+k; i<=n-k; i++) 51 for (int j=k; j<=m; j++) 52 ans=max(ans,s[i][j]+a[i-k][m]+d[i+1][1]); 53 for (int i=k; i<=n; i++) 54 for (int j=k+k; j<=m-k; j++) 55 ans=max(ans,s[i][j]+a[n][j-k]+b[n][j+1]); 56 cout<<ans; 57 return 0; 58 }