§二分L,转化为判断三个边长为L的正方形能否覆盖所有点
§求包含所有点的最小矩形
§一定至少有一个矩形覆盖在角上,枚举在哪个角
§求包含剩下的点的最小矩形
§一定至少有一个矩形覆盖在角上,再枚举在哪个角
§求包含剩下的点的最小矩形
§判断是否小于L*L
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n;
int ax[22005],ay[22005];
int mxx,mxy,mix,miy;
bool pan(int mid)
{
if (mid>mxx-mix&&mid>mxy-miy) return true;
for (int i=1;i<=4;i++)
{
int x,y;
switch(i)
{
case 1:x=mxx,y=mxy;break;
case 2:x=mxx,y=miy;break;
case 3:x=mix,y=miy;break;
case 4:x=mix,y=mxy;break;
}
int txx,txy,tix,tiy;
txx=txy=-inf;
tix=tiy=inf;
for (int j=1;j<=n;j++) if (abs(ax[j]-x)>mid||abs(ay[j]-y)>mid)
{
txx=max(txx,ax[j]);
txy=max(txy,ay[j]);
tix=min(tix,ax[j]);
tiy=min(tiy,ay[j]);
}
for (int j=1;j<=4;j++)
{
int xx,yy;
switch(j)
{
case 1:xx=txx,yy=txy;break;
case 2:xx=txx,yy=tiy;break;
case 3:xx=tix,yy=tiy;break;
case 4:xx=tix,yy=txy;break;
}
int ttxx,ttxy,ttix,ttiy;
ttxx=ttxy=-inf;
ttix=ttiy=inf;
for (int l=1;l<=n;l++)
if (abs(ax[l]-x)>mid||abs(ay[l]-y)>mid)
if (abs(ax[l]-xx)>mid||abs(ay[l]-yy)>mid)
{
ttxx=max(ttxx,ax[l]);
ttxy=max(ttxy,ay[l]);
ttix=min(ttix,ax[l]);
ttiy=min(ttiy,ay[l]);
}
if (ttxx-ttix<=mid&&ttxy-ttiy<=mid) return true;
}
}
return false;
}
int main()
{
scanf("%d",&n);
mxx=mxy=-inf;
mix=miy=inf;
for (int i=1;i<=n;i++)
{
scanf("%d%d",&ax[i],&ay[i]);
mxx=max(mxx,ax[i]);
mxy=max(mxy,ay[i]);
mix=min(mix,ax[i]);
miy=min(miy,ay[i]);
}
int l=0,r=1e9,mid,ans;
while (l<=r)
{
mid=(l+r)>>1;
if (pan(mid))
{
ans=mid;
r=mid-1;
}else l=mid+1;
}
printf("%d",ans);
return 0;
}
总结
1:这里是通过维护横纵坐标的最大最小来维护整个最小点覆盖矩形的。