题目大意:给你在n个在二维平面坐标系上的坐标,要你求出所有坐标中两点间最短的距离。
解析:求平面最近点对的核心思想是分治,用递归实现。
具体操作如下:
如点的个数很多,按现将所有点按x排序,如果x相同按照y排序,并按x坐标平均的分成左右两个部分
分别求出两边的最短距离minl与minr 并令 ans = min(minl,minr)。
求出左右两边的最小值之后,剩下的工作就是合并。
然后根据鸽巢原理:
遍历将当前的(l,l+6)的最小值点和ans比较,求其中的最小值
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int N = 10010; struct Node { double x,y; }p[N]; bool cmp(Node a,Node b) { if(a.x != b.x) { return a.x < b.x; }else { return a.y < b.y; } } double dis(Node a,Node b) { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } double solve(int l,int r) { if(l == r) { return INF; } if(r - l == 1) { return dis(p[l],p[r]); } if(r - l == 2) { double d1,d2,d3; d1 = dis(p[l],p[l+1]); d2 = dis(p[l],p[l+2]); d3 = dis(p[l+1],p[l+2]); return min(min(d1,d2),d3); } int mid = (l + r) / 2; double curMin = min(solve(l,mid),solve(mid+1,r)); for(int i = l; i <= r; i++) { for(int j = i+1; j <= r && j <= i+5; j++) { if(p[j].x - p[i].x > curMin) { continue; } curMin = min(curMin,dis(p[i],p[j])); } } return curMin; } int main() { int n; while(scanf("%d",&n) != EOF && n) { for(int i = 0; i < n; i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } sort(p,p+n,cmp); double ans = solve(0,n-1); if(ans > 10000) { printf("INFINITY\n"); }else { printf("%.4lf\n",ans); } } return 0; }