黑格覆盖(前缀和)

黑格覆盖


 
在一张由 M * N 个小正方形格子组成的矩形纸张上,有 k 个格子被涂成了黑色。给你一张由 m * n 个同样小正方形组成的矩形卡片,请问该卡片最多能一次性覆盖多少个黑格子?

输入

输入共 k+1 行:
第 1 行为 5 个整数 M、N、m、n、k,其含义如题目所述。
接下来 k 行,每行 2 个整数,分别表示被涂成黑色的格子的行、列坐标。
 

输出

输出共 1 行,1 个整数,表示卡片一次性最多能覆盖的黑格子数。

样例输入 Copy

3 5 2 2 3 1 1 2 2 3 5

样例输出 Copy

2

提示

根据样例数据所得到的涂完黑格的矩形和用于覆盖的矩形如下图所示:

对于 40%的数据:m=n;
对于 100%的数据:M、N、m、n、k 均小于等于 1000,所有黑格不重复出现。

1 分别计算每行的黑格数的前缀和,和每列的黑格数的前缀和
2   找m2=min(m1,m);    n2=min(n1,n);让卡片正放,暴力找最大值。根据容斥定理可知 ans=max(tu[i][j]-tu[i-m2][j]-tu[i][j-n2]+tu[i-m2][j-n2],ans);
3.将卡片倒放,再次暴力计算;
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e3+10;
 4  
 5 int tu[N][N]= {0};
 6 int ans;
 7 int main()
 8 {
 9     int m1,n1,m2,n2,k,m,n;
10     scanf("%d %d %d %d %d",&m1,&n1,&m,&n,&k);
11  
12     for(int i=0,x,y;i<k;i++)
13     {
14         scanf("%d %d",&x,&y);
15         tu[x][y]=1;
16     }
17  
18     for(int i=1; i<=m1; i++)
19     {
20         for(int j=1; j<=n1; j++)
21         {
22             tu[i][j]+=tu[i][j-1];
23         }
24  
25     }
26  
27     for(int i=1; i<=m1; i++)
28     {
29         for(int j=1; j<=n1; j++)
30             tu[i][j]+=tu[i-1][j];
31     }
32  
33     m2=min(m1,m);
34     n2=min(n1,n);
35     for(int i=m2; i<=m1; i++)
36     {
37         for(int j=n2; j<=n1; j++)
38         {
39             ans=max(tu[i][j]-tu[i-m2][j]-tu[i][j-n2]+tu[i-m2][j-n2],ans);
40         }
41     }
42  
43  
44     m2=min(m1,n);
45     n2=min(n1,m);
46     for(int i=m2; i<=m1; i++)
47     {
48         for(int j=n2; j<=n1; j++)
49         {
50             ans=max(ans,tu[i][j]-tu[i-m2][j]-tu[i][j-n2]+tu[i-m2][j-n2]);
51         }
52     }
53     printf("%d\n",ans);
54     return 0;
55 }

 

posted @ 2020-02-01 08:52  sylvia11  阅读(276)  评论(0编辑  收藏  举报