码迷,mamicode.com
首页 > 编程语言 > 详细

最近对算法

时间:2020-03-31 14:52:43      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:中位数   直线   坐标   names   complex   bool   new   预处理   math   

1. 问题

  p1=(x1,y1),p2=(x2,y2)...pn=(xn,yn)是平面nn个点构成的集合S,最近对问你就是找出集合S中距离最近的点对。

 

2. 解析

  采用分治法。

   1)划分:将集合S分成两个子集S1S2,根据平衡子问题原则,每个子集中大约有n/2个点,设集合S的最近点对是pipj(1<=i,j<=n

  则有以下三种情况 1.piS1,pjS1

             2.piS1,pjS2

                          3.piS2, pjS2

  (2)求解子问题:对于划分阶段的情况12可递归求解

    通过直线x=M(中位数),将空间划为两部分,x<Mx>M分别求出左右最近点对距离,d1,d2,d=min(d1,d2)则,只需考虑3,x-dxd的区域之间的最近点对,按照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));
}

 

 

 

最近对算法

标签:中位数   直线   坐标   names   complex   bool   new   预处理   math   

原文地址:https://www.cnblogs.com/powerkeke/p/12604554.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!