BZOJ_1052_[HAOI2007]_覆盖问题_(二分+贪心)

描述


http://www.lydsy.com/JudgeOnline/problem.php?id=1052

网格图,给出\(n\)个点,要求用3个边长相同的正方形覆盖所有点,求最小边长.

 

分析


显然是二分+判断可行性.

如何判断可行性呢?我们注意到是3个正方形.为什么是3个?

我们先找出覆盖所有点的最小距形,那么距形的四条边必须有正方形贴着,而又是3个正方形,所以至少要有1个正方形同时贴着两条边.

1.贴着的边相对

这样的话三个正方形都同时贴着相对的两条边,比如是上下两条边,那么贴着左边的那个正方形就贴着3条边,在距形的一角.

2.贴着的边相邻

这样的话这个正方形就在距形的一角.

所以我们递归的把正方形放在距形的一角,然后去掉已经覆盖了的点,继续放正方形即可.

 

 

 1 #include <bits/stdc++.h>
 2 #define fst first
 3 #define scd second
 4 using namespace std;
 5 inline int read(int &x){x=0;int k=1;char c;for(c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')k=-1;for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';return x*=k;}
 6 
 7 typedef pair <int,int> P;
 8 const int maxn=20000+5,INF=0x7fffffff;
 9 int n,ml,mr,mu,md;
10 P a[maxn];
11 bool vis[maxn];
12 bool dfs(int x,int t){
13     if(t==3) return max(md-mu,mr-ml)<=x;
14     P b[4][2];
15     b[0][0]=P(ml,mu),b[0][1]=P(ml+x,mu+x);
16     b[1][0]=P(ml,md-x),b[1][1]=P(ml+x,md);
17     b[2][0]=P(mr-x,mu),b[2][1]=P(mr,mu+x);
18     b[3][0]=P(mr-x,md-x),b[3][1]=P(mr,md);
19     for(int i=0;i<4;i++){
20         int tl=ml,tr=mr,tu=mu,td=md;
21         int tmp[maxn];
22         for(int j=1;j<=n;j++) tmp[j]=vis[j];
23         for(int j=1;j<=n;j++)
24                 if(a[j].fst>=b[i][0].fst&&a[j].fst<=b[i][1].fst&&a[j].scd>=b[i][0].scd&&a[j].scd<=b[i][1].scd)
25                     vis[j]=true;
26         mu=ml=INF; mr=md=-INF;
27         for(int j=1;j<=n;j++)if(!vis[j]){
28             mu=min(mu,a[j].scd); md=max(md,a[j].scd);
29             ml=min(ml,a[j].fst); mr=max(mr,a[j].fst);
30         }
31         bool flag=dfs(x,t+1);
32         ml=tl,mr=tr,mu=tu,md=td;
33         for(int j=1;j<=n;j++) vis[j]=tmp[j];
34         if(flag) return true;
35     }
36     return false;
37 }
38 inline void solve(){
39     int l=0,r=max(md-mu,mr-ml);
40     while(l<r){
41         for(int i=1;i<=n;i++)if(vis[i]) puts("!");
42         int mid=l+(r-l)/2;
43         if(dfs(mid,1)) r=mid;
44         else l=mid+1;
45     }
46     printf("%d\n",l);
47 }
48 inline void init(){
49     read(n);
50     mu=ml=INF,mr=md=-INF;
51     for(int i=1;i<=n;i++){
52         read(a[i].fst), read(a[i].scd);
53         ml=min(ml,a[i].fst); mr=max(mr,a[i].fst);
54         mu=min(mu,a[i].scd); md=max(md,a[i].scd);
55     }
56 }
57 int main(){
58     init();
59     solve();
60     return 0;
61 }
View Code

 

 

1052: [HAOI2007]覆盖问题

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1540  Solved: 705
[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

Source

 

posted @ 2016-07-07 10:12  晴歌。  阅读(527)  评论(0编辑  收藏  举报