题目大意:给你在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;
}
本文介绍了一种利用分治法解决二维平面上最近点对问题的方法。通过递归将点集分为两部分,分别计算左右两侧最短距离,再通过鸽巢原理合并结果,最终得到所有点对间的最短距离。
&spm=1001.2101.3001.5002&articleId=40189203&d=1&t=3&u=73ae01268be4471a832b4199450cb625)
250

被折叠的 条评论
为什么被折叠?



