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; }
时间: 2024-10-12 19:09:34