这个题如果能想到的话还算简单。。。
但是思路似乎。。。反正我想不出来
我们首先对于一堆点,记录xy分别的min和Max,一共四个值
当正方形数目小于等于三个的时候,其中一个正方形一定以这四个点中的一个点为顶点
然后枚举就好了。。。
自己写的代码打死都过不去,后来进入了无意义的发呆调试。。所以后来看了别人的代码。。。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define inf 0x7fffffff/2 #define MIN -inf #define MAX 20009 #define ll long long #define rep(i,j,k) for(int i=j;i<=k;i++) using namespace std; int n,done[MAX],now=0; int x[5],y[4]; int vis[MAX],ans; struct point { int x,y; }a[MAX]; bool check(int len) { rep(i,0,1) rep(j,0,1) { int sum=0,sum2,now_x=x[i],now_y=y[j]; int xx[2]={inf,-inf},yy[2]={inf,-inf}; memset(done,0,sizeof(done)); rep(k,1,n) if(abs(a[k].x-now_x)<=len&&abs(a[k].y-now_y)<=len) done[k]=1,sum++; else xx[0]=min(xx[0],a[k].x), xx[1]=max(xx[1],a[k].x), yy[0]=min(yy[0],a[k].y), yy[1]=max(yy[1],a[k].y); if(sum==n) return 1; rep(k,0,1) rep(p,0,1) { int sum2=sum; now_x=xx[k],now_y=yy[p]; int maxx=-inf,minx=inf,maxy=-inf,miny=inf; rep(l,1,n) if(!done[l]) if(abs(a[l].x-now_x)<=len&&abs(a[l].y-now_y)<=len) sum2++; else maxx=max(maxx,a[l].x), minx=min(minx,a[l].x), maxy=max(maxy,a[l].y), miny=min(miny,a[l].y); if(sum2==n) return 1; if(maxx-minx<=len&&maxy-miny<=len) return 1; } } return 0; } int main() { scanf("%d",&n); x[0]=y[0]=inf; x[1]=y[1]=-inf; rep(i,1,n) scanf("%d%d",&a[i].x,&a[i].y), x[0]=min(x[0],a[i].x),x[1]=max(x[1],a[i].x), y[0]=min(y[0],a[i].y),y[1]=max(y[1],a[i].y); int l=0,r=1000000000; while(l<r-1) { int mid=(l+r)>>1,t=check(mid); printf("%d %d %d %d\n",l,mid,r,t); if(t) ans=mid,r=mid; else l=mid; } printf("%d\n",check(l)?l:r); return 0; }
bzoj1052 HAOI2007 覆盖问题,布布扣,bubuko.com
原文:http://blog.csdn.net/wbysr/article/details/23019033