【问题描述】

给定二维平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。使用递归与分治策略求解二维平面上的最接近点对问题。假设所有点的集合为S,m为S中所有点的x坐标的中位数,垂直线x=m将集合S均匀分割为左右两个子集合S1和S2。

[输入]:

在屏幕上输入点的个数,以及所有点的x和y坐标。

[输出]:

第一次分割时,将所有点集合S分割为左右两个子集合S1和S2,分别输出左右子集合S1和S2,以及所有点集合S的最接近点对的距离以及最接近点对。

[样例输入]:

10

-15.4 -57.3

13.2 30.1

-87.5 93.2

47.6 -12.7

94.7 61.5

56.8 -57.1

27.8 43.5

-28.1 19.0

-96.2 47.5

55.5 -93.3

[样例输出]:

42.8

-28.1 19.0

13.2 30.1

36.2

55.5 -93.3

56.8 -57.1

19.8

13.2 30.1

27.8 43.5

[样例说明]:

输入:10个点,后续每行为每一点的x和y坐标。

输出:左右子集合S1和S2,以及所有点集合S的最接近点对的距离以及最接近点对。例如,前面三行中,S1的最接近点对的距离为42.8,最接近点对的x和y坐标分别为(-28.1,19.0)和(13.2,30.1)。输出最接近点对坐标时,先输出的点的x坐标小于后输出点的x坐标。中间三行和最后三行分别为子集合S2和集合S的最接近点对的距离以及最接近点对。

[问题分析]:

平面最近点对问题属于递归与分治类问题,此问题可以从一维最近点对问题开始研究:

当我们处理一个一维最近点对问题时,通过递归与分治的思想,我们可以不断对其进行二分,通过先对一维线上的点进行排序(此步骤是为了找中位数点的时候方便),然后找到这些点中的中位数mid,然后依此中位数为划分标准,对所有的点集合进行二分,划分为左集合和右集合,以此递归,在每层递归中,分别找到划分的左右集合中的最近点对,并选出最近的那一点对,然后再检查是否存在两个点一个在左集合,一个在右集合而这两点间的距离小于刚才找到的最近点对的距离(当然前人已经证明:如果最近点对出现在这种情况,在被划分的左右集合中最多各有一个点)。

然后再将此情景推广到二维平面点集合,划分标准中位数mid则由点集合中每个点的x坐标来求,mid也可以被看作是一条垂直的线x=mid,将这个二维平面进行了划分。接下来的步骤就跟一维最近点对问题的处理方法大致相同,不同的是,在出现最近点对的两个点是一个位于左集合,一个位于右集合时,不再是在被划分的左右集合中最多各有一个点,而是可能在左边出现n/2个点,右边最多出现6个点(这个结论前人也已经进行了证明)。

[算法步骤]:

1.将所有点按照x的进行排序

2.用x=mid将整个平面划分为两部分

3.求出x<=mid部分的最近点对距离d_left,求出x>mid部分的最近点对距离d_right,求出这两者中最小的距离记为d

4.找出所有x坐标在(mid-d,mid+d)范围中的点,放入res

5.对于(x,y),x∈(mid-d,mid),如果点(x1,y1)中x1>mid且|y-y1|<d,那么记录两点间距离,如果小于d,那么更新d,否则检查下一个点,以此类推,直至遍历完res中所有的点。

[伪代码]:

if(r-l==1) return dis(node[l],node[r])

if(r-l==2) return min(dis(node[l],node[r]),min(dis(node[l],node[l+1]),dis(node[l+1],node[r])))

else

sort(node,node+n,by_X)

mid=(l+r)/2

d=min(closet(node,l,mid),closet(node,mid+1,r))

for i=l to r

if(fabs(node[i].x-node[mid].x)<d) res.push_back(node[i])

sort(res.begin(),res.end(),by_Y)

for i=0 to res.size

for j=i+1 to res.size

if(fabs(res[i].y-res[j].y)<d)

min_dis=dis(res[i],res[j])

if(min_dis<d) d=min_dis

[时间复杂度分析]:

T(n)=1           当k=2时

T(n)=2T(n/2)+n   当k>2时

所以T(n)=O(nlog2n)

[代码实现]:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<bits/stdc++.h>
using namespace std;
typedef struct Point
{double x,y;
}Point;Point node[1000];
int n;double dis(Point a,Point b)
{return sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2));
}bool by_X(Point a,Point b)//按x大小排序
{if(a.x==b.x) return a.y<b.y;else return a.x<b.x;
}bool by_Y(Point a,Point b)//按y大小排序
{if(a.y==b.y) return a.x<b.x;else return a.y<b.y;
}void swap(Point &a,Point &b)
{Point c=a;a=b;b=c;
}
double closet(int l,int r,Point *best_node)
{if(r-l==1)//两个点的情况 {best_node[0]=node[l];best_node[1]=node[r]; return dis(node[l],node[r]);}else if(r-l==2)//三个点的情况 {double dis1=dis(node[l],node[l+1]);double dis2=dis(node[l+1],node[r]);double dis3=dis(node[l],node[r]);if(dis1<dis2&&dis1<dis3){best_node[0]=node[l];best_node[1]=node[l+1];return dis1;}if(dis2<dis1&&dis2<dis3){best_node[0]=node[l+1];best_node[1]=node[r];return dis2;}if(dis3<dis2&&dis3<dis1){best_node[0]=node[l];best_node[1]=node[r];return dis3;}}else//大于三个点的情况 { int mid=(l+r)/2;Point temp1[2],temp2[2];double d_left=closet(l,mid,best_node);temp1[0]=best_node[0];temp1[1]=best_node[1];if(mid==(0+n-1)/2) //为了保证是在最外一层递归(即第一次分割的时候)的时候再输出 {printf("%.1lf\n",d_left);if(temp1[0].x>temp1[1].x) swap(temp1[0],temp1[1]);printf("%.1lf %.1lf\n",temp1[0].x,temp1[0].y);printf("%.1lf %.1lf\n",temp1[1].x,temp1[1].y);} double d_right=closet(mid+1,r,best_node);temp2[0]=best_node[0];temp2[1]=best_node[1];if(mid==(0+n-1)/2) {printf("%.1lf\n",d_right);if(temp2[0].x>temp2[1].x) swap(temp2[0],temp2[1]);printf("%.1lf %.1lf\n",temp2[0].x,temp2[0].y);printf("%.1lf %.1lf\n",temp2[1].x,temp2[1].y);}double d;if(d_left<=d_right){d=d_left;best_node[0]=temp1[0];best_node[1]=temp1[1];}if(d_left>d_right){d=d_right;best_node[0]=temp2[0];best_node[1]=temp2[1];} vector<Point> res;for(int i=l;i<=r;i++)//将距离mid距离小于d的点放入res {if(fabs(node[i].x-node[mid].x)<d){res.push_back(node[i]);}}sort(res.begin(),res.end(),by_Y);//将res中的点按照y的大小进行排序,便于后面的筛选 for(int i=0;i<res.size();i++)//通过i,j遍历res中所有的点对,从而找到距离最近的点对 {for(int j=i+1;j<res.size();j++){if(fabs(res[i].y-res[j].y)>d) break;double min_dis=dis(res[i],res[j]);if(min_dis<d){d=min_dis;best_node[0]=res[i];best_node[1]=res[j];}}}  return d;   }}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n;double d;for(int i=0;i<n;i++){cin>>node[i].x;cin>>node[i].y;}    Point best_node[2];//记录最近点对 sort(node,node+n,by_X);d=closet(0,n-1,best_node); printf("%.1lf\n",d);if(best_node[0].x>best_node[1].x) swap(best_node[0],best_node[1]);printf("%.1lf %.1lf\n",best_node[0].x,best_node[0].y);printf("%.1lf %.1lf",best_node[1].x,best_node[1].y);} 

【算法分析与设计】平面最近点对(含最近距离、最近点对、第一次分割点集合的输出)相关推荐

  1. 算法分析与设计——分治法最近点对

    分治法最近点对 分治法 分治法将一个难以直接解决的大问题划分成一些规模较小的子问题,分别求解各个子问题,再合并子问题的解得到原问题的解. 一般来说,分治法的求解过程由以下三个阶段组成: 划分:把规模为 ...

  2. 深大算法设计与分析实验二——分治法求最近点对问题

    源代码: 深大算法设计与分析实验二--分治法求最近点对问题代码-C/C++文档类资源-CSDN下载 目录 实验问题 一.实验目的: 二.内容: 三.算法思想提示 产生不重复的随机点算法: 蛮力算法: ...

  3. NJUPT算法分析与设计期末考试202.12.1

    NJUPT算法分析与设计期末考试2021.11.24 判断 简答 1.算法是什么?算法的时间复杂度是什么?衡量的原则,标准,工具 2.分支限界法扩展活节点的方式有哪两种,有什么差别? 3.回溯法搜索子 ...

  4. 算法分析与设计课程复习之回溯法

    算法分析与设计课程复习之回溯法 一.基本思想 1.解空间 设问题的解向量为X=(x1,x2,-,xn) ,xi的取值范围为有穷集Si .把xi的所有可能取值组合,称为问题的解空间.每一个组合是问题的一 ...

  5. 算法分析与设计课程设计-Dijkstra最短路径算法

    算法分析与设计课程设计报告书       题目:Dijkstra最短路径算法 设计人:张钦颖 班级:14计科2班    学号:1414080901218 一.     实验环境: 1.硬件环境:个人机 ...

  6. 程振波 算法设计与分析_算法分析与设计之动态规划

    动态规划同样是一种将问题分解为求解子问题的方法,不过与分治不同的是,动态规划算法的子问题不是相互独立的,而是有公共的部分,即有重叠子问题,这个时候使用分治算法,将会重复计算公共的子问题,效率很低!而用 ...

  7. MYSQL交通系统查询,城市公交查询系统的设计与实现(SSH,MySQL)(含录像)

    城市公交查询系统的设计与实现(SSH,MySQL)(含录像)(开题报告,毕业论文15000字,程序代码,MySQL数据库,答辩PPT) 本文针对公交站的查询实际情况(百度地图),按照软件工程的结构化设 ...

  8. 一本好的教辅,可以少走很多弯路:算法分析和设计 王晓东

    算法分析和设计 王晓东 我觉得第三版JAVA版本最好,第4版是C++版本,删减了几章. 可以配合北大屈婉玲教授的视频课程一起看 自己走了一些弯路,希望后续的可以避免以下 下载地址如下,也可以淘宝买本二 ...

  9. hfss螺旋平面_利用HFSS设计平面等角螺旋天线

    - 73 - 利用 HFSS 设计平面等角螺旋天线 杜起飞 北京理工大学电子工程系 100081 摘要:本文介绍了一种双臂平面等角螺旋天线的设计过程,利用 ANSOFT HFSS 对其结构进行了建 模 ...

最新文章

  1. ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API
  2. 风电功率预测matlab,一种基于二十四节气的风电功率预测方法与流程
  3. 为rm命令增加回收站功能
  4. boost::ignore_unused的用法实例
  5. 双稳态电路的两个稳定状态是什么_从双稳态到双“更”稳态 ——叶芳伟课题组在拓扑光子学研究方向上取得新进展...
  6. Toad for Oracle 导入MIP.dmp文件时:报内存不足时的解决办法:
  7. uni-app集成uview
  8. 蓝桥杯第八届省赛JAVA真题----包子凑数
  9. android 不同项目代码合并在一块,android - 是否可以将两个(正在积极开发中的)Android应用程序模块合并到同一个Android Studio项目中? - 堆栈内存溢出...
  10. go语言 格式化输出
  11. 数据:DeFi总锁定价值突破170亿美元
  12. 剑指offer之 从尾到头打印链表
  13. 【为书豪相亲】单身小姐姐你在哪里,我是书豪,我在等你
  14. Presentation Prompter for Mac(屏幕提词器)
  15. 计算机中键盘可以共享吗,两个电脑怎么共用一个键盘
  16. LaTeX学习:Texlive 2019和TeX studio的安装及使用
  17. FPGA——基于Verilog HDL语言的交通信号灯控制系统
  18. Excel同时打开多个窗口
  19. 联想台式计算机设置u盘启动不了,联想扬天M4000e台式电脑bios设置U盘启动图文方法...
  20. SpringBoot集成RabbitMQ实现消息重试机制,消息重试3次失败后写入死信队列,消息重试3次失败后入库

热门文章

  1. java规则引擎Aviator
  2. 日文xp系统中 日文键盘模式转英式键盘模式
  3. Unity3D——脚本编程
  4. Raspbian安装ROS系统Kinectic
  5. 变形金刚5的口碑崩盘,教会了我什么
  6. 数据库系统原理复习题目【总】
  7. android 落叶效果,css实现落叶动画效果
  8. 【剑指offer】登峰造极 -- 树的子结构
  9. 20165221学习基础和C语言基础调查
  10. 惊动 这些年为什么越来越多的人叫它二手东?自身监管不严?