枚举(分类讨论):BZOJ 1177: [Apio2009]Oil

1177: [Apio2009]Oil

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 1477  Solved: 589
[Submit]

Description

采 油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井。被拍卖的整块土地为一个矩形区域,被划分为M×N个小块。 Siruseri地质调查局有关于Navalur土地石油储量的估测数据。这些数据表示为M×N个非负整数,即对每一小块土地石油储量的估计值。 为了避免出现垄断,政府规定每一个承包商只能承包一个由K×K块相连的土地构成的正方形区域。 AoE石油联合公司由三个承包商组成,他们想选择三块互不相交的K×K的区域使得总的收益最大。 例如,假设石油储量的估计值如下: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 8 8 8 8 8 1 1 1 1 8 8 8 8 8 1 1 1 1 8 8 8 8 8 1 1 1 1 1 1 1 8 8 8 1 1 1 1 1 1 1 1 8 8 8 1 1 1 1 1 1 9 9 9 1 1 1 1 1 1 9 9 9 如果K = 2, AoE公司可以承包的区域的石油储量总和为100, 如果K = 3, AoE公司可以承包的区域的石油储量总和为208。 AoE公司雇佣你来写一个程序,帮助计算出他们可以承包的区域的石油储量之和的最大值。

Input

输入第一行包含三个整数M, N, K,其中M和N是矩形区域的行数和列数,K是每一个承包商承包的正方形的大小(边长的块数)。接下来M行,每行有N个非负整数表示这一行每一小块土地的石油储量的估计值

Output

输出只包含一个整数,表示AoE公司可以承包的区域的石油储量之和的最大值。

Sample Input

9 9 3
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 1 1 1 8 8 8 1 1
1 1 1 1 1 1 8 8 8
1 1 1 1 1 1 9 9 9
1 1 1 1 1 1 9 9 9

Sample Output

208
  
  这道题很妙啊,其实只要分类讨论就可以了。
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=1510;
 6 int Ul[maxn][maxn],Ur[maxn][maxn];
 7 int Dl[maxn][maxn],Dr[maxn][maxn];
 8 int a[maxn][maxn];
 9 
10 int sum(int x,int y,int k)
11 {
12     if(x<k||y<k)return 0;
13     return a[x][y]-a[x-k][y]-a[x][y-k]+a[x-k][y-k];
14 }
15 
16 void Pre_Solve(int R,int C,int K)
17 {
18     for(int i=K;i<=R;i++)
19         for(int j=K;j<=C;j++){
20             int S=sum(i,j,K);
21             Ul[i][j]=S;
22             Ur[i][j-K+1]=S;
23             Dl[i-K+1][j]=S;
24             Dr[i-K+1][j-K+1]=S;
25         }
26     
27     for(int i=1;i<=R;i++)
28         for(int j=1;j<=C;j++)
29             Ul[i][j]=max(Ul[i][j],max(Ul[i-1][j],Ul[i][j-1]));
30             
31     for(int i=1;i<=R;i++)
32         for(int j=C;j>=1;j--)
33             Ur[i][j]=max(Ur[i][j],max(Ur[i-1][j],Ur[i][j+1]));
34     
35     for(int i=R;i>=1;i--)
36         for(int j=1;j<=C;j++)
37             Dl[i][j]=max(Dl[i][j],max(Dl[i+1][j],Dl[i][j-1]));
38             
39     for(int i=R;i>=1;i--)
40         for(int j=C;j>=1;j--)
41             Dr[i][j]=max(Dr[i][j],max(Dr[i+1][j],Dr[i][j+1]));
42 }
43 int ans=0;
44 void Solve(int R,int C,int K)
45 {
46     for(int i=1;i<=R;i++){
47         for(int j=1;j<=C;j++){
48             ans=max(ans,Ul[i][C]+Dl[i+1][j]+Dr[i+1][j+1]);
49             ans=max(ans,Ul[i][j]+Ur[i][j+1]+Dr[i+1][1]);
50             ans=max(ans,Ul[i][j]+Dl[i+1][j]+Dr[1][j+1]);
51             ans=max(ans,Ul[R][j]+Ur[i][j+1]+Dr[i+1][j+1]);
52         }
53     }    
54     for(int i=2*K;i<R;i++){
55         int MaxS=0;
56         for(int j=1;j<=C;j++)
57             MaxS=max(MaxS,sum(i,j,K));
58         ans=max(ans,Ul[i-K][C]+MaxS+Dr[i+1][1]);
59     }
60     for(int j=2*K;j<C;j++){
61         int MaxS=0;
62         for(int i=1;i<=R;i++)
63             MaxS=max(MaxS,sum(i,j,K));
64         ans=max(ans,Ul[R][j-K]+MaxS+Dr[1][j+1]);
65     }
66 }
67 int main()
68 {
69 #ifndef ONLINE_JUDGE
70     freopen("oil.in","r",stdin);
71     freopen("oil.out","w",stdout);
72 #endif    
73     int R,C,K;
74     scanf("%d%d%d",&R,&C,&K);
75     for(int i=1;i<=R;i++)
76         for(int j=1;j<=C;j++){
77             scanf("%d",&a[i][j]);
78             a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
79         }
80     Pre_Solve(R,C,K);
81     Solve(R,C,K);
82     printf("%d\n",ans);
83 } 

 

 
posted @ 2016-03-14 17:00  TenderRun  阅读(180)  评论(0编辑  收藏  举报