/*
通过这题对分治、递归均有了更深一层的理解。
花在理解和coding上的时间值得了 */
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
typedef struct Node
{
double x, y;
}Node;
Node array[100010];
Node a[100010];
const int inff = 65535;
bool cmpx(Node a, Node b)
{
return a.x < b.x;
}
bool cmpy(Node a, Node b)
{
return a.y < b.y;
}
double Euc(Node a, Node b)
{
return sqrt( (a.x - b.x) * (a.x- b.x) + (a.y - b.y) * (a.y - b.y));
}
double min(double x, double y)
{
return x < y ? x : y;
}
double minDist(int lower, int upper)
{
//base情况:1点、2点、3点间的最小距离都可以直接求出
if(lower == upper)
{
return inff;
}
if(lower + 1 == upper)
{
return Euc(array[lower], array[upper]);
}
if(lower + 2 == upper)
{
return min( Euc(array[lower], array[lower + 1]), min( Euc(array[lower], array[upper]), Euc(array[lower + 1], array[upper]) ) );
}
//normal情况:递归求取最小距离 分两种情况:1、minDist来自左边或者右边
// 2、minDist点对分跨左右
int midX = (lower + upper) >> 1; //X中心点划分
double lMin = minDist(lower, midX); //左
double rMin = minDist(midX+1, upper); //右
double delta = min(lMin, rMin);
int i,t = 0;
//memset(a, 0, sizeof(a));
for(i = lower; i <= upper; ++i) //filter,如果 x-midX 都大于delta了,就不用考虑
{
if(array[i].x >= array[midX].x - delta && array[i].x <= array[midX].x + delta)
{
a[t++] = array[i];
}
}
sort(a, a+t, cmpy);
double tmpDelta;
for(i = 0; i < t - 1; ++i)
{
int flag = 0;
for(int j = i + 1; j < t; ++j, ++flag)
{
if(flag > 7) //优化:由鸽笼定理,对于任取的左点p,最多不超过7个右点满足 dist(p, q) <= delta
break; //理解这个花了比较久的时间
tmpDelta = Euc(a[i], a[j]);
if(tmpDelta < delta)
delta = tmpDelta;
}
}
return delta;
}
int main(void)
{
//freopen("1.txt", "r", stdin);
int N;
double re;
while(cin >> N, N)
{
int i = 0;
while(N--)
{
cin >> array[i].x >> array[i].y;
i++;
}
sort(array, array + i, cmpx);
re = minDist(0, i - 1) / 2;
printf("%.2f\n", re);
//cout << minDist(0, i - 1) / 2 << endl;
//memset(array, 0, sizeof(array));
}
return 0;
}
HDU1007_分治_找最小距离点对
最新推荐文章于 2021-03-22 21:08:16 发布