最近对算法
Posted powerkeke
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近对算法相关的知识,希望对你有一定的参考价值。
1. 问题
设p1=(x1,y1),p2=(x2,y2)...pn=(xn,yn)是平面n上n个点构成的集合S,最近对问你就是找出集合S中距离最近的点对。
2. 解析
采用分治法。
(1)划分:将集合S分成两个子集S1和S2,根据平衡子问题原则,每个子集中大约有n/2个点,设集合S的最近点对是pi和pj(1<=i,j<=n)
则有以下三种情况 1.pi∈S1,pj∈S1
2.pi∈S1,pj∈S2
3.pi∈S2, pj∈S2
(2)求解子问题:对于划分阶段的情况1和2可递归求解
通过直线x=M(中位数),将空间划为两部分,x<M和x>M分别求出左右最近点对距离,d1,d2,另d=min(d1,d2)则,只需考虑3,即x-d和xd的区域之间的最近点对,按照Y坐标对区域内点进行排序,如果一个点对的距离小于d,他们一定在d*(2*d)的区域内。
3. 设计
1.预处理:对点集合S={(x1,y1),(x2,y2)......(xn,yn)}按照x坐标升序排列
2.如果n=2,则返回连点之间距离
3.计算{(x1,y1),(x2,y2).....(xm,ym)}之间的最近距离d1
计算{(xm,ym)(xm+1,ym+1)....(xn,yn)}之间的最近距离d2
d=min(d1,d2)
4.依次计算S[l...r]的最近点对(将集合按照y升序排列,考察y-s[m].y<d的点)
l=min(i)| S[m]-S[i]<d
r=max(i)| S[i]-S[m]<d
4. 分析
O(nlogn)
5. 源码
/*
author: keke
project name:最近对算法
Time Complexity: O(nlogn)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const int INF = 0x7fffffff;
int n;
struct Point {
double x,y;
Point(double x=0, double y=0):x(x),y(y) {}
bool operator < (const Point& p) const {
if(x != p.x)return x < p.x;
else return y < p.y;
}
} p[200000+5],temp[200000+5];
bool cmpy(Point a, Point b) {
return a.y < b.y;
}
double Dis(Point a, Point b) {
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double Closest_Pair(int left, int right) {
double d = INF;
if(left == right)
return d;
if(left +1 == right)
return Dis(p[left],p[right]);
int mid = (left+right)>>1;
double d1 = Closest_Pair(left,mid);
double d2 = Closest_Pair(mid,right);
d = min(d1,d2);
int k = 0;
for(int i = left; i <= right; i++) {
if(fabs(p[mid].x - p[i].x) <= d)
temp[k++] = p[i];
}
sort(temp,temp+k,cmpy);
for(int i = 0; i < k; i++) {
for(int j = i+1; j < k && temp[j].y - temp[i].y < d; j++) {
double d3 = Dis(temp[i],temp[j]);
d = min(d,d3);
}
}
return d;
}
int main() {
cin>>n;
for(int i=0; i<n; i++) {
double a,b;
scanf("%lf%lf",&a,&b);
p[i] = Point(a,b);
}
sort(p,p+n);
printf("%.3f",Closest_Pair(0,n-1));
}
以上是关于最近对算法的主要内容,如果未能解决你的问题,请参考以下文章
有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]