bzoj1052 HAOI2007 覆盖问题

这个题如果能想到的话还算简单。。。

但是思路似乎。。。反正我想不出来


我们首先对于一堆点,记录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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值