分治法求最接近点对问题
2016-04-16 23:36
302 查看
问题描述:在点集P中,找出这样的一对点,使得他们之间的距离在点集P中每两两所组成的所有点对中距离最小。(当然,这样的点对可能不止一组,但我们只要求输出一组即可。)
为了便于理解,我们循序渐进的来讨论这个问题,从中我们也慢慢体会分治算法的精妙之处。
首先说说一维情况:
即假设这些点都位于一条直线上(x坐标轴上),采用分治法思想,考虑将所给的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。如果这2个点分别在S1和S2中呢?此时我们可能就会想到按照x坐标的顺序从左到右对他们进行排序了,排序之后,如果说这2个点分别在S1和S2中,那么必定是S1的最后一个点(S1中x坐标最大的)和S2中的第一个点(S2中x坐标最小的)。依此思路给出如下代码:
“`
为了便于理解,我们循序渐进的来讨论这个问题,从中我们也慢慢体会分治算法的精妙之处。
首先说说一维情况:
即假设这些点都位于一条直线上(x坐标轴上),采用分治法思想,考虑将所给的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。如果这2个点分别在S1和S2中呢?此时我们可能就会想到按照x坐标的顺序从左到右对他们进行排序了,排序之后,如果说这2个点分别在S1和S2中,那么必定是S1的最后一个点(S1中x坐标最大的)和S2中的第一个点(S2中x坐标最小的)。依此思路给出如下代码:
#include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <ctype.h> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <string> #include <vector> #define eps 1e-8 #define INF 0x7fffffff #define PI acos(-1.0) #define seed 31//131,1313 typedef long long LL; typedef unsigned long long ULL; using namespace std; const int maxn=100005; struct Point{ double x; }p[maxn]; int a[maxn]; int cmpx(Point a,Point b){ return a.x<b.x; } inline double dis(Point a,Point b){ if(a.x>b.x) return a.x-b.x; else return b.x-a.x; } double closest(int low,int high){ if(low+1==high) //只有两个点 return dis(p[low],p[high]); if(low+2==high) //只有三个点 return min(dis(p[low],p[high]),min(dis(p[low],p[low+1]),dis(p[low+1],p[high]))); int mid=(low+high)/2; //求中点即左右子集的分界线 double d=min(closest(low,mid),closest(mid+1,high)); d=min(d,dis(p[mid],p[mid+1])); //最后一步,合并 return d; } int main() { int n; while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++) scanf("%lf",&p[i].x); sort(p,p+n,cmpx); printf("%.2lf\n",closest(0 , n-1));//最近点对间的距离 } return 0; }
“`
相关文章推荐
- 2015年简短总结
- HDU 5666 快速乘
- leetcode 16: 3 Sum closest (C#版)
- MFC CStatic类动态创建
- VLC播放RTSP视频延迟问题
- 利用链表实现多项式求值
- VS2013中 scanf()函数返回值
- Jersey(1.19.1) - Security
- Linux防止“rm -rf /”误操作的方法
- Merge OUTPUT 高级用法综合写的一个MergeTab的存储过程
- POJ-1655 Balancing Act
- 数据平台的简单使用
- SLAM学习
- Django:之ORM、CMS和二维码生成
- Windows server 2012R2安装活动目录
- 方便学习的一些经典网站
- HDU 5665
- 使用 PDO 方式将 Session 保存到 MySQL 数据中
- 抛砖微信公众号应用开发
- mysql 下载及安装方法