http://acm.hdu.edu.cn/showproblem.php?pid=1007
给出n个玩具(抽象为点)的坐标 求套圈的半径 要求最多只能套到一个玩具
实际就是要求最近的两个坐标的距离
典型的最近点对问题
最近点对详解
http://blog.csdn.net/lonelycatcher/article/details/7973046
//最近点对
# include <stdio.h>
# include <algorithm>
# include <math.h>
# define MAX 100005
# define INF 100000000
using namespace std;
struct POINT
{
double x, y;
}arr[MAX];
int n, temp[MAX];
bool cmp(const POINT& a, const POINT& b)
{
if(a.x != b.x)
return a.x < b.x;
return a.y < b.y;
}
bool cmp2(const int& a, const int& b)
{
return arr[a].y < arr[b].y;
}
double dis(int a, int b)
{
return sqrt(pow(arr[a].x - arr[b].x, 2) + pow(arr[a].y - arr[b].y, 2));
}
double min(double a, double b)
{
return a<b?a:b;
}
double closest_pointpair(int left, int right)
{
double d = INF;
if(left == right)//单个点不计算直接返回INF
return d;
if(left + 1 == right)//相邻点直接计算距离
return dis(left, right);
int mid = (left + right) / 2;//取区间中值
d = min(closest_pointpair(left, mid), closest_pointpair(mid+1, right));//分治 取二者中的小数作为领域范围
int num = 0;
for(int i = left; i <= right; i++)//记录中值两边+(-)d范围内的所有点的下标
if(fabs(arr[mid].x - arr[i].x) <= d)
temp[num++] = i;
sort(temp, temp+num, cmp2);//按y从小到大排序
for(int i = 0; i < num; i++)//两两枚举 若距离小于d 替换
{
for(int j = i + 1; j < num && arr[temp[j]].y - arr[temp[i]].y < d; j++)
{
double dt = dis(temp[i], temp[j]);
d = min(d, dt);
}
}
return d;//返回当前分域最近点对距离
}
int main()
{
while(scanf("%d", &n) && n)
{
for(int i = 0; i < n; i++)
scanf("%lf %lf",&arr[i].x, &arr[i].y);
sort(arr, arr+n, cmp);
printf("%.2lf\n", closest_pointpair(0, n-1) / 2);
}
return 0;
}