经典问题之最近点对问题

来源:互联网 发布:暴风城先锋长戟数据 编辑:程序博客网 时间:2024/04/29 05:23

解决问题:在平面内有n个点,求两两之间的最短距离。


题解:

1.枚举点,打擂台。O(n^2)


2.分治。先按x坐标排序,以中位数画一条线,将平面分成两个部分,对两个左右部分分别处理,然后合并。


合并:设总区间d=min{左区间d,右区间d}划分左右之后,按照y的大小归并两个区间的点坐标,然后以d为上届,刷去一些点,对于剩下的点直接左右互相算距离,打擂台即可。效率经证明为O(nlog n).


参考程序:

#include<cstdio>#include<algorithm>#include<vector>#include<cmath>#define maxn 21000#define INF 0x7f7f7f7fusing namespace std;int n;struct Pair{int x,y;bool operator < (const Pair& rhs) const {return x<rhs.x;}}loc[maxn];bool cmp_y(Pair a,Pair b){return a.y<b.y;}double closeset_pair(Pair *a,int n){if (n<=1)return INF;int m=n/2;double x=a[m].x;double d=min(closeset_pair(a,m),closeset_pair(a+m,n-m));inplace_merge(a,a+m,a+n,cmp_y);vector<Pair> b;for (int i=0;i<n;i++){if (fabs(a[i].x-x)>=d)continue;    for (int j=0;j<b.size();j++){double dx=a[i].x-b[b.size()-j-1].x;double dy=a[i].y-b[b.size()-j-1].y;if (dy>=d)break;d=min(d,sqrt(dx*dx+dy*dy));}b.push_back(a[i]);}return d;}int main(){scanf("%d",&n);for (int i=0;i<n;i++)scanf("%d%d",&loc[i].x,&loc[i].y);sort(loc,loc+n);printf("%f",closeset_pair(loc,n));return 0;}


0 0
原创粉丝点击