题意:
给你n个全在一个平面上点的坐标,求相邻最近的点的距离的一半是多少。
思路:
(我只能说杭电真是高大上,一个课件里面的题都如此不简单,膜拜中。。。。)
因为有10万个点,所以两层循环的暴力肯定过不了。
这是一个分治的思想:
1.算出左边的点组成的集合最小值d1,再算出右边的点组成的集合最小值d2,合并这两个值求最小的d。
不过,还有可能这两个最近距离的点是分别在左边的点集和右边的点集,所以需要第二步。
2.只有两边的点的距离小于d,那么这个两个点才有价值。那可以推出只有这个点离中间的点的距离小于d才有价值,
进一步就是在x轴上的距离如果小于d才有价值。那么,我们就可以对这些点的x坐标做升序排列,筛选出离中间点的x轴上的距离d的点。
再对这些筛选出来的点求两个之间的距离。不过,如果被筛选出来的点还是很多呢,我们现在还有一个y坐标没有利用。
3.对筛选出来的点对y做升序排列,选取第一个点和后面的点求距离,然后再选取第二个点进行求距离,以此类推,在每次求值得过程中,
如果距离大于d,那么就可以break。(因为后面的点肯定比前面的距离要远)
Code:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include<cctype>
#include<vector>
#define TEST
#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define xep(i, n) for(int i = 0; i < (n); ++i)
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#define dep(i, s, e) for(int i = (s); i >= (e); --i)
#ifdef TEST
#define See(a) cout << #a << " = " << a << endl;
#define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
#define debug(a, s, e){ rep(_i, s, e) {cout << a[_i] << ' '; }cout << endl;}
#define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee);}
#else
#define See(a) {}
#define See2(a, b) {}
#define debug(a, s, e) {}
#define debug2(a, s, e, ss, ee) {}
#endif
const int MAX = 2e9;
const int MIN = -2e9;
const double PI = acos(-1.0);
const double eps = 1e-9;
using namespace std;
const int N = 100000 + 5;
struct Point
{
double x, y;
Point(){}
Point(double x, double y) : x(x), y(y) {}
double dis(Point &b)
{
return sqrt((x - b.x) * (x - b.x) + (y - b.y) * (y - b.y));
}
double X(Point &b)
{
return fabs(x - b.x);
}
double Y(Point &b)
{
return fabs(y - b.y);
}
}e[N], tem[N];
bool cmpx(Point a, Point b)
{
return a.x < b.x;
}
bool cmpy(Point a, Point b)
{
return a.y < b.y;
}
int n;
double getDis(int st, int ed)
{
double ret = 0;
int mid = st + (ed - st) / 2;
if(st + 1 == ed)
{
return e[st].dis(e[ed]);
}
if(st + 2 == ed)
{
return min(e[st].dis(e[ed]), min(e[mid].dis(e[st]), e[mid].dis(e[ed])));
}
ret = min(getDis(st, mid), getDis(mid + 1, ed));
int num = 0;
rep(i, st, ed)
{
if(e[i].x >= e[mid].x - ret && e[i].x <= e[mid].x + ret)
{
tem[num++] = e[i];
}
}
sort(tem, tem + num, cmpy);
xep(i, num)
{
rep(k, i + 1, num - 1)
{
if(tem[i].Y(tem[k]) < ret)
{
ret = tem[i].dis(tem[k]);
}
else
{
break;
}
}
}
return ret;
}
int main()
{
while(~scanf("%d", &n) && n)
{
xep(i, n)
{
scanf("%lf%lf", &e[i].x, &e[i].y);
}
sort(e, e + n, cmpx);
printf("%.2f\n", getDis(0, n - 1) / 2);
}
return 0;
}