Description
看过隋唐演义的都知道“宇文成都”是天下第二武功高手,就在隋炀帝杨广被奸臣宇文化及(也就是宇文成都的父亲)所逼死,宫中一片大乱,然“宇文成都”是一代豪杰,不愿通过这种方式来取得皇位,于是只身一人与上万瓦岗起义军决战,以死报国。(可惜啊,这么好的一个人,跟错了主)。
宇文成都 只身一人击退起义军多位大将,就在这时,徐茂公准备下令让所有士兵冲上去活捉 宇文成都 ,然而 宇文成都 已经发现,他甚至记住了所有士兵的位置(在平面直角坐标系上的坐标,均为整数),他现在可以使用师傅传授的武功,将一个长度为L的正方形(平行于坐标轴,顶点坐标为整数)区域全部化为灰烬,L正比与他所消耗的功力,然而因为刚才运力过多,他现在只能使用3次武功,每一次的攻击正方形边长L都相同,三次使用武功后,他的体力总损耗为 L,每一次选择的正方形区域可以不同,也可以相交。现在他要把所有的n个士兵全部消灭,请问他最少要消耗多少体力(即最小正方形边长)?
(每次使用武功可将正方形内部的士兵全部消灭,边界上也算)
Input
第一行一个整数n(n个士兵),接下来n行,每行两个整数(xi,yi),表示每个士兵的坐标。
Output
共一行,一个整数,表示最小的体力消耗(L)。
Sample Input
10
10 3
4 8
9 1
1 6
5 5
9 6
6 7
7 8
2 1
9 7
10 3
4 8
9 1
1 6
5 5
9 6
6 7
7 8
2 1
9 7
Sample Output
5
HINT
100%的数据:1<=n<=20000;-1000000000<=xi,yi<=1000000000;
这不就是1052么!我程序都没改。。
二分L。
验证:
先取个可以覆盖所有点的最小矩形。感觉一下,肯定有一个正方形的一个角在这个矩形的一个角上。枚举四个位置。剩下的再这么做。再枚举,最后判断一个正方形可不可以覆盖所有就行了。
#include<cstdio>
#include<algorithm>
using namespace std;
struct point
{
int x,y;
bool flag;
}p[20001],tp[20001];
struct matrix
{
int x,y;
}mat[11];
int maxx,maxy,minx,miny;
int n;
inline void find(int d,int lim)
{
int i,j;
bool flag;
for(i=1;i<=n;i++)
{
flag=true;
for(j=1;j<=d;j++)
{
if(p[i].x>=mat[j].x&&p[i].x<=mat[j].x+lim&&p[i].y>=mat[j].y&&p[i].y<=mat[j].y+lim)
{
flag=false;
break;
}
}
if(flag)
{
maxx=max(maxx,p[i].x);
maxy=max(maxy,p[i].y);
minx=min(minx,p[i].x);
miny=min(miny,p[i].y);
}
}
}
inline bool check(int lim)
{
int p=1;
int i,j,k;
for(i=1;i<=4;i++) //1左上 2左下 3右上 4右下
{
maxx=-1000000000;
maxy=-1000000000;
minx=1000000000;
miny=1000000000;
find(0,lim);
if(i==1)
{
mat[1].x=minx;
mat[1].y=miny;
}
else if(i==2)
{
mat[1].x=maxx-lim;
mat[1].y=miny;
}
else if(i==3)
{
mat[1].x=minx;
mat[1].y=maxy-lim;
}
else if(i==4)
{
mat[1].x=maxx-lim;
mat[1].y=maxy-lim;
}
for(j=1;j<=4;j++)
{
maxx=-1000000000;
maxy=-1000000000;
minx=1000000000;
miny=1000000000;
find(1,lim);
if(j==1)
{
mat[2].x=minx;
mat[2].y=miny;
}
else if(j==2)
{
mat[2].x=maxx-lim;
mat[2].y=miny;
}
else if(j==3)
{
mat[2].x=minx;
mat[2].y=maxy-lim;
}
else if(j==4)
{
mat[2].x=maxx-lim;
mat[2].y=maxy-lim;
}
maxx=-1000000000;
maxy=-1000000000;
minx=1000000000;
miny=1000000000;
find(2,lim);
if(maxx-minx<=lim&&maxy-miny<=lim)
return true;
}
}
return false;
}
int main()
{
scanf("%d",&n);
int i;
int mix=1000000000,miy=1000000000,mxx=-1000000000,mxy=-1000000000;
for(i=1;i<=n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
mxx=max(mxx,p[i].x);
mxy=max(mxy,p[i].y);
mix=min(mix,p[i].x);
miy=min(miy,p[i].y);
}
int l=1,r=max(mxx-mix+1,mxy-miy+1);
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))
r=mid-1;
else
l=mid+1;
}
printf("%d\n",l);
return 0;
}
/*
5
0 0
0 1
0 2
0 3
0 4
*/