题目大意:用三个L*L的正方形覆盖坐标系中的所有点,求L的最小值
题解:二分,转为判定性问题
找到围住所有剩余点的最小矩形,枚举四个角,放一个正方形,然后就产生了一个子问题,递归下去就可以了
YY一下贪心的正确性
边界上至少有四个点,有一个正方形要覆盖两个点,就要贴在角上……
如果有四个正方形就不成立了……
我的收获:23333
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define M 20100
struct P{int x,y;}a[M];
int n,ans,v[M];
int stack[M],top;
inline void clearcover(int x){while(top!=x) v[stack[top--]]=0;}
bool check(int x,int L)
{
if(top==n) return true;
if(x==4) return false;
int u=INF,d=-INF,l=INF,r=-INF,Start=top;
for(int i=1;i<=n;i++) if(!v[i])
u=min(u,a[i].x),d=max(d,a[i].x),
l=min(l,a[i].y),r=max(r,a[i].y);
int dx[]={u,u,d-L,d-L};
int dy[]={l,r-L,l,r-L};
for(int k=1;k<=4;k++){
for(int i=1;i<=n;i++)
if(!v[i]&&a[i].x>=dx[k]&&a[i].x<=dx[k]+L&&a[i].y>=dy[k]&&a[i].y<=dy[k]+L)
v[i]=1,stack[++top]=i;
bool flag=check(x+1,L);
clearcover(Start);
if(flag)
return true;
}
return false;
}
void work()
{
for(int l=1,r=INF;l<=r;){
int mid=l+r>>1;
if(check(1,mid)) r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<endl;
}
void init()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
}
int main()
{
init();
work();
return 0;
}