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 }

 

posted @ 2017-03-07 21:33  ws_ccd  阅读(184)  评论(0编辑  收藏  举报