BZOJ 1052 [HAOI2007] 覆盖问题(DFS)

 

题目大意

 

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

 

数据范围

100%的数据,-1,000,000,000<=Xi,Yi<=1,000,000,000

30%的数据,N<=100

50%的数据,N<=2000

100%的数据,N<=20000

 

补充:L 是一个整数

 

做法分析

 

由于是要求用三个边长相同的正方形覆盖所有的点,可以考虑二分正方形的变长,那么剩下的问题就是怎么根据一个给定的变长,确定是否三个这样的正方形能够将素有的点覆盖完

先用一个尽量小的矩形区域将没有覆盖的点框起来,那么,我们用于覆盖的正方形必然有一个顶角在矩形的四个顶角之一,这样覆盖是最优的

那么,我们只需要 DFS 一遍即可,DFS 的深度为 2,每次 DFS 有四个选择方向,这样做在时间上完全可行

 

参考代码

 

BZOJ 1052 [HAOI2007] 覆盖问题(DFS)
 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdio>

 4 

 5 using namespace std;

 6 

 7 typedef long long LL;

 8 

 9 const int N=20005;

10 const LL INF=(1LL)<<60;

11 

12 struct Point {

13     LL x, y;

14 } p[N];

15 int n, vs[N];

16 

17 void Find(LL &Maxx, LL &Minx, LL &Maxy, LL &Miny) {

18     Maxx=Maxy=-INF, Minx=Miny=INF;

19     for(int i=0; i<n; i++) if(!vs[i]) {

20         Maxx=max(Maxx, p[i].x);

21         Maxy=max(Maxy, p[i].y);

22         Minx=min(Minx, p[i].x);

23         Miny=min(Miny, p[i].y);

24     }

25 }

26 

27 bool DFS(LL R, int dep) {

28     LL Maxx, Minx, Maxy, Miny;

29     Find(Maxx, Minx, Maxy, Miny);

30     if(Maxx==-INF) return true;

31     if(dep==3) {

32         if(max(Maxx-Minx, Maxy-Miny)<=R) return true;

33         return false;

34     }

35 

36     for(int i=0; i<n; i++) if(!vs[i]) {

37         if(p[i].x>=Maxx-R && p[i].x<=Maxx && p[i].y>=Maxy-R && p[i].y<=Maxy) vs[i]=dep;

38     }

39     if(DFS(R, dep+1)) return true;

40     for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0;

41 

42     for(int i=0; i<n; i++) if(!vs[i]) {

43         if(p[i].x>=Maxx-R && p[i].x<=Maxx && p[i].y>=Miny && p[i].y<=Miny+R) vs[i]=dep;

44     }

45     if(DFS(R, dep+1)) return true;

46     for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0;

47 

48     for(int i=0; i<n; i++) if(!vs[i]) {

49         if(p[i].x>=Minx && p[i].x<=Minx+R && p[i].y>=Miny && p[i].y<=Miny+R) vs[i]=dep;

50     }

51     if(DFS(R, dep+1)) return true;

52     for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0;

53 

54     for(int i=0; i<n; i++) if(!vs[i]) {

55         if(p[i].x>=Minx && p[i].x<=Minx+R && p[i].y>=Maxy-R && p[i].y<=Maxy) vs[i]=dep;

56     }

57     if(DFS(R, dep+1)) return true;

58     for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0;

59 

60     return false;

61 }

62 

63 bool check(LL R) {

64     fill(vs, vs+n, 0);

65     return DFS(R, 1);

66 }

67 

68 int main() {

69     while(scanf("%d", &n)!=EOF) {

70         for(int i=0; i<n; i++) {

71             scanf("%lld%lld", &p[i].x, &p[i].y);

72             vs[i]=0;

73         }

74         LL Maxx, Minx, Maxy, Miny;

75         Find(Maxx, Minx, Maxy, Miny);

76         LL L=0, R=max(Maxx-Minx, Maxy-Miny);

77         while(L<R) {

78             int mid=(L+R)>>1;

79             if(check(mid+1)) R=mid;

80             else L=mid+1;

81         }

82         if(!check(L)) L++;

83         printf("%lld\n", L);

84     }

85     return 0;

86 }
BZOJ 1052

 

题目链接 & AC 通道

 

BZOJ 1052 [HAOI2007] 覆盖问题

 

 

 

你可能感兴趣的:(2007)