关闭

【bzoj1052】【HAOI2007】【覆盖问题】【贪心】

195人阅读 评论(0) 收藏 举报
分类:

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。

           对于判断,首先用一个最小的矩阵去覆盖树苗。显然塑料薄膜应该放到矩阵的角上。

           然后我们先暴力放两个薄膜,然后判断剩下的点能否放到一个薄膜里。

代码:

#include<iostream>
#include<cstdio>
#define N 20010
#define INF 1000000000
using namespace std;
int n,l,r,mid,ans;
struct use{int x[N],y[N],mx;}p,q;
void del(use &t,int x,int y,int xx,int yy){
 int n=t.mx;t.mx=0;
 for (int i=1;i<=n;i++)if (t.x[i]<x||t.x[i]>xx||t.y[i]<y||t.y[i]>yy){t.x[++t.mx]=t.x[i];t.y[t.mx]=t.y[i];}
}
void cal(use &t,int kind,int l){
  int x(INF),xx(-INF),y(INF),yy(-INF);
  for (int i=1;i<=t.mx;i++){
    x=min(x,t.x[i]);y=min(y,t.y[i]);xx=max(xx,t.x[i]);yy=max(yy,t.y[i]);
    }
  if (kind==1)del(t,x,y,x+l,y+l);if (kind==2)del(t,xx-l,y,xx,y+l);
  if (kind==3)del(t,x,yy-l,x+l,yy);if (kind==4)del(t,xx-l,yy-l,xx,yy);
}
bool check(int v){  
  for (int i=1;i<=4;i++)
   for (int j=1;j<=4;j++){
    int x(INF),xx(-INF),y(INF),yy(-INF);
      for (int k=1;k<=n;k++) q.x[k]=p.x[k],q.y[k]=p.y[k];
       q.mx=n;cal(q,i,v);cal(q,j,v);
      for (int k=1;k<=q.mx;k++){x=min(x,q.x[k]);y=min(y,q.y[k]);xx=max(xx,q.x[k]);yy=max(yy,q.y[k]);}
      if (xx-x<=v&&yy-y<=v) return true;
   }
  return false;
}
int main(){
  scanf("%d",&n);p.mx=n;l=1;r=INF;
  for (int i=1;i<=n;i++)  scanf("%d%d",&p.x[i],&p.y[i]);     
  while (l<=r){mid=(l+r)>>1;if (check(mid)){ans=mid;r=mid-1;}else l=mid+1;}
  printf("%d\n",ans);
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:196644次
    • 积分:6355
    • 等级:
    • 排名:第3844名
    • 原创:455篇
    • 转载:1篇
    • 译文:0篇
    • 评论:5条
    最新评论