BZOJ1052 [HAOI2007]覆盖问题

1052: [HAOI2007]覆盖问题

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2401  Solved: 1101
[Submit][Status][Discuss]

Description

  某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄
膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建
立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行与坐标轴,一个点如果在
正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。

Input

  第一行有一个正整数N,表示有多少棵树。接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证
不会有2个树的坐标相同。

Output

  一行,输出最小的L值。

Sample Input

4
0 1
0 -1
1 0
-1 0

Sample Output

1

HINT

 

100%的数据,N<=20000

 

 很容易想到二分L的长度,但是check合法性很麻烦。容易得出,如果用一个矩形包围所有点,那么长度为L的正方形的最优策略一定是位于矩形的四个角中的其中一个,枚举四个角,然后把位于小正方形内的点全部剔除,就变成了用两个小正方形覆盖所有点的子问题,于是用dfs直到第三层处理完后看是否涵盖所有点即可。

一开始tmp数组和cnt开成了全局变量,导致dfs过程中会不断覆盖之前的值...调了好久

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 struct Node{
 5     int x,y;
 6 };
 7 Node a[20050];
 8 int vis[20050];
 9 
10 void cut(int minx,int miny,int maxx,int maxy,int &cnt,int tmp[]){
11     for (int i = 0;i < n;++i){
12         if (a[i].x >= minx && a[i].x <= maxx && a[i].y >= miny && a[i].y <= maxy) {
13             vis[i]++;
14             tmp[cnt++] = i;
15         }
16     }
17 }
18 
19 bool check(int L,int step){
20     if (step == 3) {
21         for (int i = 0;i < n;++i){
22             if (!vis[i]) return false;
23         }
24         return true;
25     }
26     int minx,miny,maxx,maxy;
27     minx = miny = 1e9+7;
28     maxx = maxy = -1e9+7;
29     for (int i = 0;i < n;++i){
30         if (vis[i]) continue;
31         minx = min(minx,a[i].x);
32         miny = min(miny,a[i].y);
33         maxx = max(maxx,a[i].x);
34         maxy = max(maxy,a[i].y);
35     }
36 
37     int cnt = 0,tmp[20050];
38     cut(minx,miny,minx+L,miny+L,cnt,tmp);
39     if (check(L,step+1)) return true;
40     for (int i = 0;i < cnt;++i){
41         vis[tmp[i]]--;
42     }
43 
44     cnt = 0;
45     cut(minx,maxy-L,minx+L,maxy,cnt,tmp);
46     if (check(L,step+1)) return true;
47     for (int i = 0;i < cnt;++i) vis[tmp[i]]--;
48 
49     cnt = 0;
50     cut(maxx-L,maxy-L,maxx,maxy,cnt,tmp);
51     if (check(L,step+1)) return true;
52     for (int i = 0;i < cnt;++i) vis[tmp[i]]--;
53 
54     cnt = 0;
55     cut(maxx-L,miny,maxx,miny+L,cnt,tmp);
56     if (check(L,step+1)) return true;
57     for (int i = 0;i < cnt;++i) vis[tmp[i]]--;
58     return false;
59 }
60 
61 
62 int main(){
63     scanf("%d",&n);
64     for (int i = 0;i < n;++i){
65         scanf("%d%d",&a[i].x,&a[i].y);
66     }
67     int l = 0;
68     int r = 1e9+7;
69     while(l < r){
70         int mid = (l+r) >> 1;
71         memset(vis,0,sizeof(vis));
72         if (check(mid,0)) r = mid;
73         else l = mid+1;
74     }
75     printf("%d\n",l);
76     return 0;
77 }

 

posted @ 2018-08-29 14:55  mizersy  阅读(141)  评论(0编辑  收藏  举报