1052: [HAOI2007]覆盖问题
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1611 Solved: 741
[ 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
0 1
0 -1
1 0
-1 0
Sample Output
1
HINT
100%的数据,N<=20000
Source
题解:二分+dfs
二分答案然后判定长度是否可行,因为正方形区域一定是卡着剩余的点的两个边界的,所以枚举卡那个边界即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 20003
#define inf 1000000003
using namespace std;
int n,m,minn,maxn,vis[N];
struct data{
int x,y;
}a[N];
int cmp(data a,data b)
{
return a.x<b.x||a.x==b.x&&a.y<b.y;
}
int check()
{
for (int i=1;i<=n;i++) if (!vis[i]) return 0;
return 1;
}
bool dfs(int x,int t)
{
if (t==4) {
if (check()) return 1;
else return 0;
}
if (check()) return 1;
int xmax=-inf; int ymax=-inf; int xmin=inf; int ymin=inf;
for (int i=1;i<=n;i++)
if (!vis[i]) ymax=max(ymax,a[i].y),xmax=max(xmax,a[i].x),xmin=min(xmin,a[i].x),ymin=min(ymin,a[i].y);
bool f=false;
for (int i=1;i<=n;i++)
if (!vis[i]&&a[i].x>=xmax-x&&a[i].y>=ymax-x) vis[i]=t;
if (dfs(x,t+1)) f=true;
for (int i=1;i<=n;i++)
{
if (vis[i]==t) vis[i]=0;
if (!vis[i]&&a[i].x<=xmin+x&&a[i].y<=ymin+x) vis[i]=t;
}
if (dfs(x,t+1)) f=true;
for (int i=1;i<=n;i++) {
if (vis[i]==t) vis[i]=0;
if (!vis[i]&&a[i].x<=xmin+x&&a[i].y>=ymax-x) vis[i]=t;
}
if (dfs(x,t+1)) f=true;
for (int i=1;i<=n;i++) {
if (vis[i]==t) vis[i]=0;
if (!vis[i]&&a[i].x>=xmax-x&&a[i].y<=ymin+x) vis[i]=t;
}
if (dfs(x,t+1)) f=true;
for (int i=1;i<=n;i++) if (vis[i]==t) vis[i]=0;
if (f) return 1;
return 0;
}
int main()
{
freopen("cover.in","r",stdin);
freopen("cover.out","w",stdout);
scanf("%d",&n);
maxn=-inf; minn=inf;
for (int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y),maxn=max(maxn,a[i].x),maxn=max(maxn,a[i].y),
minn=min(minn,a[i].x),minn=min(minn,a[i].y);
sort(a+1,a+n+1,cmp);
int l=0; int r=maxn-minn+1;
int ans=r;
while (l<=r) {
int mid=(l+r)/2;
memset(vis,0,sizeof(vis));
if (dfs(mid,1)) ans=min(ans,mid),r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}