[HAOI2007]覆盖问题

题目描述

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

输入输出格式

输入格式:

第一行有一个正整数N,表示有多少棵树。

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

输出格式:

一行,输出最小的L值。

输入输出样例

输入样例#1: 复制
4
0 1
0 -1
1 0
-1 0
输出样例#1: 复制
1

说明

数据范围

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

30%的数据,N<=100

50%的数据,N<=2000

100%的数据,N<=20000

二分答案ans

求出最大的包括n个点的矩形

说明至少有一个正方形与外包矩形有两条边及以上相接,就是一个公共角

于是我们可以对于前两个正方形枚举与哪个角相接,对于第三个正方形判断就行了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long lol;
 8 struct Data
 9 {
10   int top;
11   int x[20001],y[20001];
12 }a;
13 int Minx,Miny,Maxx,Maxy,n,ans;
14 void cut(Data &b,int x1,int x2,int y1,int y2)
15 {int i;
16   int tot=0;
17   for(i=1;i<=b.top;i++)
18     {
19       if ((b.x[i]<x1||b.x[i]>x2)||(b.y[i]<y1||b.y[i]>y2))
20       b.x[++tot]=b.x[i],b.y[tot]=b.y[i];
21     }
22   b.top=tot;
23 }
24 void work(Data &b,int c,int mid)
25 {int i;
26   Maxx=-1e9;Minx=1e9;
27   Maxy=-1e9;Miny=1e9;
28   for (i=1;i<=b.top;i++)
29     {
30       Maxx=max(Maxx,b.x[i]);Minx=min(Minx,b.x[i]);
31       Maxy=max(Maxy,b.y[i]);Miny=min(Miny,b.y[i]);
32     }
33   if (c==1)
34     {
35       cut(b,Minx,Minx+mid,Miny,Miny+mid);
36     }
37   if (c==2)
38     {
39       cut(b,Minx,Minx+mid,Maxy-mid,Maxy);
40     }
41   if (c==3)
42     {
43       cut(b,Maxx-mid,Maxx,Maxy-mid,Maxy);
44     }
45   if (c==4)
46     {
47       cut(b,Maxx-mid,Maxx,Miny,Miny+mid);
48     }
49 }
50 bool check(int mid)
51 {int x,y,i,x1,y1,x2,y2;
52   Data b;
53   for (x=1;x<=4;x++)
54     {
55       for (y=1;y<=4;y++)
56     {
57       b.top=a.top;
58       for (i=1;i<=b.top;i++)
59         {
60           b.x[i]=a.x[i];b.y[i]=a.y[i];
61         }
62       work(b,x,mid);work(b,y,mid);
63       x1=-1e9;x2=1e9;
64       y1=-1e9;y2=1e9;
65       for (i=1;i<=b.top;i++)
66         {
67           x1=max(x1,b.x[i]);x2=min(x2,b.x[i]);
68           y1=max(y1,b.y[i]);y2=min(y2,b.y[i]);
69         }
70       if (x1-x2<=mid&&y1-y2<=mid) return 1;
71     }
72     }
73   return 0;
74 }
75 int main()
76 {int i;
77   cin>>n;
78   for (i=1;i<=n;i++)
79     {
80       scanf("%d%d",&a.x[i],&a.y[i]);
81     }
82   a.top=n;
83   int l=0,r=1e9;
84   while (l<=r)
85     {
86       int mid=(l+r)/2;
87       if (check(mid)) ans=mid,r=mid-1;
88       else l=mid+1;
89     }
90   cout<<ans;
91 }

 

posted @ 2018-03-03 16:17  Z-Y-Y-S  阅读(220)  评论(0编辑  收藏  举报