• 算法分析与实践-作业5


    最近对问题

    1. 问题

    n个点在公共空间中,求出所有点对的距离最小值。

    2. 解析

    ①    对所有的点按照x坐标从小到大排序。根据下标进行分割,使得点集分为两个集合。

    ②    递归的寻找两个集合中的最近点对。取两个集合最近点对中的最小值min(dis_left,dis_right)。

    ③    最近距离不一定存在于两个集合中,可能一个点在集合A,一个点在集合B,而这两点间距离小于dis。这其中如何合并是关键。根据递归的方法可以计算出划分的两个子集中所有点对的最小距离dis= min(dis_left,dis_right)。那么一个点在集合A,一个在集合B中的情况,可以针对此情况,用之前分解的标准值,即按照x坐标从小到大排序后的中间点的x坐标作为mid,划分一个[mid−dis,mid+dis]区域,如果存在最小距离点对,必定存在这个区域中。

     

    之后只需要根据[mid−dis,mid]左边区域的点来遍历右边区域[mid,mid+dis]的点,即可找到是否存在小于dis距离的点对。

    3. 设计

     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 const int maxn = 1000 + 10;
     7 struct Point {
     8     int x, y;
     9     Point(int _x = 0, int _y = 0) :x(_x), y(_y) {}
    10     bool operator < (const Point& rhs)const {
    11         return x < rhs.x;
    12     }
    13 };
    14 int n;
    15 bool cmp(struct Point& a, struct Point& b) {     //按照x坐标从小到大排序
    16     return a.x < b.x;
    17 }
    18 bool cmp2(struct Point& a, struct Point& b) { //按照y坐标从小到大排序
    19     return a.y < b.y;
    20 }
    21 double Dis(Point a, Point b) {
    22     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    23 }
    24 
    25 double ClosestPoint(vector<Point> points, int left, int right) {
    26     if (right - left < 2)return 0x3f3f3f3f;
    27     if (right - left == 2) {
    28         return Dis(points[left], points[right - 1]);
    29     }
    30     if (right - left == 3) {
    31         double d1 = Dis(points[left], points[right - 1]);
    32         double d2 = Dis(points[left], points[right - 2]);
    33         double d3 = Dis(points[right - 2], points[right - 1]);
    34         return min(d1, min(d2, d3));
    35     }
    36     int mid = (right + left) / 2;
    37     int mm = points[mid].x;
    38     double dl = ClosestPoint(points, left, mid);  //左边区域最短距离
    39     double dr = ClosestPoint(points, mid, right);    //右边区域最短距离
    40     double minn = min(dl, dr);
    41     vector<Point>v;
    42     for (int i = left; i < mid; ++i) {
    43         if (mm - points[i].x <= minn)
    44             v.push_back(points[i]);
    45     }
    46     for (int i = mid; i < right; ++i) {
    47         if (points[i].x - minn <= mm)
    48             v.push_back(points[i]);
    49     }
    50     sort(v.begin(), v.end(), cmp2);
    51     double mindist = 0x3f3f3f3f;
    52     for (int i = 0; i < v.size(); ++i) {            //处理分隔线两边的点
    53         for (int j = i+1; j < v.size(); ++j) {
    54             if (abs(v[i].y - v[j].y) < minn) {
    55                 double d = Dis(v[i], v[j]);
    56                 if (d < minn) mindist = d;
    57             }
    58             else {
    59                 break;
    60             }
    61         }
    62     }
    63     return min(minn, mindist);
    64 }
    65 
    66 int main() {
    67     vector<Point>points;
    68     scanf("%d", &n);
    69     for (int i = 1; i <= n; ++i) {
    70         Point point;
    71         scanf("%d %d", &point.x, &point.y);
    72         points.push_back(point);
    73     }
    74     sort(points.begin(), points.end(), cmp);
    75     printf("%.2f
    ", ClosestPoint(points, 0, n));
    76 }

    4. 分析

    因此整体的时间复杂度为O(nlogn)。

    5. 源码

    https://github.com/JayShao-Xie/algorithm-work/blob/master/ClosestPoint.cpp

  • 相关阅读:
    常见HTTP状态(304,)
    面试错题集
    从零构建以太坊(Ethereum)智能合约到项目实战——学习笔记1
    windows 以太坊开发框架Truffle环境搭建
    Ollydbg使用问题汇总
    网络攻防实战技术之——缓冲区溢出篇
    如何批量删除.svn文件
    树莓派安装nextcloud、Seafile
    汇编语言从入门到精通-5微机CPU的指令系统2
    kali安装vm tools正确操作
  • 原文地址:https://www.cnblogs.com/JayShao/p/12562431.html
Copyright © 2020-2023  润新知