分治法求最近点对

2024-02-20 08:38
文章标签 分治 最近 法求

本文主要是介绍分治法求最近点对,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Dvide and Conquer

Implement the algorithm for the closest pair problem in your favourite language.

INPUT: n points in a plane.

OUTPUT: The pair with the least Euclidean distance.


算法的思想:

首先对所有的点按照x坐标进行从小到大排序,然后利用二分法进行分割,直到区间范围变为2 or 3(即只有2个点或只有3个点),然后可以求这2个点或是3个点的距离(很小的子问题)。

对于每一部分子问题,求其中间mid左右各min范围内的点的距离,如图:

对于这幅图中,只需将绿色的点与右边3个红色的点比较即可(格子按1/2&距离分割,可以保证每个格子内只有1个点)。


对于这幅图,只需将绿色的点与左边6个点比较即可

这里,当我们按照y坐标进行排序后(不考虑x坐标),因此对于每一个点,只需要将其与附近的11个点比较即可。

算法的合并时间:边界附近的点进行排序需要O(nlogn)。

如果每一次迭代保持2个序列,一个按照x进行排序,一个按照y进行排序,像归并排序一样,将预先排序好的2个方向的序列合并起来,实际上只需要0(n)时间。

因此算法的时间复杂度为T(n)=2T(n)+O(n)=0(nlogn)。


input:

-5,-5
-4,-4
-3,-6
-3,-3
-2,-3
-1,-5
0,-3
1,-4
0.5,-3
0.5,-4

output:


#include<iostream>  
#include<string.h>
#include<math.h>
#include <fstream>
#include<iomanip>
#include<algorithm> 
using namespace std;
int k=0; struct Record
{int c1,c2;double ds;
}record[10000];struct Points
{double x,y;
}*points;double dis(int a,int b)
{double dx = points[a].x-points[b].x,dy = points[a].y-points[b].y;return sqrt(dx*dx+dy*dy);
}double min(double a,double b)
{return a>b?b:a;
}int cmpx(const Points &a,const Points &b)    
{  if(a.x<b.x)   return 1;    else  return 0;   
}  int cmpy(const Points &a,const Points &b)    
{  if(a.y<b.y)   return 1;    else  return 0;   
}  void storage(double c,int l,int r)
{	//记录最近点对,用于输出record[k].c1 = l;record[k].c2 = r;record[k++].ds = c;
}double ClosestPair(int l, int r)
{if(1==r-l){double d = dis(l,r);storage(d,l,r);return d;}if(2==r-l){double ll = dis(l,l+1);double rr = dis(l+1,r);storage(ll,l,l+1);storage(rr,l+1,r);return min(ll,rr);}int mid = l+((r-l)>>1);double dl = ClosestPair(l,mid);double dr = ClosestPair(mid+1,r);double Min=min(dl,dr);int h1=mid,h2=mid;while((points[mid].x-points[h1].x<=Min && h1>=l) || (points[h2].x-points[mid].x<=Min && h2<=r)){	//得到mid附近2&距离内的区间范围h1--;h2++;}sort(&points[l],&points[r],cmpy); //将mid附近2&距离内的点按照y坐标从小到大排序for(int i=h1+1;i<h2;i++){int k=(i+11)>h2?h2:(i+11);	//只需要比较附近11个点即可for(int j=i+1;j<k;j++){double d=dis(i,j);if(d>=Min)break;Min = d;storage(d,i,j);}}return Min;
}int main()
{ifstream infile("./points.txt", ios::in); char buf[30];double (*data)[2];	char *subarr=NULL;char *delims = ",";int n;cout<<"Please input the number of points(eg.input 10 int this test):"<<endl;cin>>n;points = new struct Points[n];data = new double[n][2];if(!infile.is_open()){cout<<"Error opening file!";exit(1);}int i=0,j=0,p=0;while(infile.getline(buf,30)!=NULL){j = 0;subarr = strtok(buf,delims);while(subarr!=NULL){data[i][j] = atof(subarr);	subarr = strtok(NULL,delims);j++;}points[p].x = data[i][0];points[p++].y = data[i][1];i++;}infile.close();sort(&points[0],&points[n],cmpx); //按横坐标从小到大排序double value = ClosestPair(0,n-1);int x,y;for(i=0;i<k;i++){if(record[i].ds==value){x = record[i].c1;y = record[i].c2;cout<<"points("<<points[x].x<<","<<points[x].y<<")and("<<points[y].x<<","<<points[y].y<<")"<<endl;}}cout<<"have the shortest distance :"<<value<<endl;return 0;
}


这篇关于分治法求最近点对的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/727629

相关文章

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

最近心情有点复杂:论心态

一月一次的彷徨又占据了整个身心;彷徨源至不自信;而不自信则是感觉自己的价值没有很好的实现亦或者说是自己不认可自己的目前的生活和状态吧。 我始终相信一句话:任何人的生活形态完全是由自己决定的;外在的总归不能直达一个人的内心深处。所以少年 为了自己想要的生活 多坚持努力吧、不为别人只为自己心中的那一丝执着。 由此我看到了一个故事: 一个心情烦躁的人去拜访禅师。他问禅师:我这辈子就这么注定了吗?您

在二叉树中找到两个节点的最近公共祖先(基于Java)

如题  题解 public int lowestCommonAncestor(TreeNode root, int o1, int o2) {//记录遍历到的每个节点的父节点。Map<Integer, Integer> parent = new HashMap<>();Queue<TreeNode> queue = new LinkedList<>();parent.put(roo

算法图解(8~10贪心,动态规划,K最近邻算法)

贪心算法 在每一步都选择局部最优解,从而期望最终得到全局最优解。 贪心算法并不总能保证全局最优解,因此需要满足以下两个条件: 贪心选择性质:可以通过局部最优选择构造出全局最优解。最优子结构:问题的最优解包含其子问题的最优解。 实例:给定面额的硬币,用最少硬币凑出指定金额 int minCoins(vector<int>& coins, int amount) {int count = 0

救命!我已经彻底被最近的FLUX模型征服了

这是一期FLUX模型配套的罗拉模型推荐,这个大模型真的很香,尤其是对于人物的手部处理,推荐大家去尝试下,我已经爱上这个大模型了。 ① Flux魅影超模 https://www.liblib.art/modelinfo/15818662ba2e443d9b4f9a87c13fff55 关键词:照片上是一位优雅的年轻女子,一头棕色卷发,身穿米色上衣,戴着金耳环。她背对着相机,背景是浅色的。重点是

redis 实现单位时间内错误记录 时间到key值就被清除------最近脑子不好使觉得还是写个博客试试

直接在客户端操作的, 所以需要redis的简单命令  去对比JAVA客户端jedis的命令就行   添加---set     格式 set  key  value  EX time(秒)   如果这个time不添加的话 ,那默认就是 永久 获取--get    格式 get key  ---查看剩余时间    格式 TTL key ---实现key实现自增: inrc key

最近刚接触用到的一些linux命令(CentOS7的命令)二〇一八年十月三十日

linux  查看本地     ip  ip addr  查看本地系统     #cat /etc/issue 在CentOS下执行显示为: CentOS release 5.7 (Final) Kernel \r on an \m 或在Ubuntu下显示为: Ubuntu 11.04 \n \l 可以用来查看当前正在运行的 Ubuntu 的版本号。  查看系统内核     uname -a

最近做阿里的笔试题,美团的笔试题都出现了栈的顺序的问题。

问题描述:   已知abcdef,依次入栈,在栈中可停留也可出栈,求下面哪个出栈的顺序不正确?或者有多少种出栈的顺序? f(0):1 f(1):1 f(2):2 f(3):5 f(4):14 f(5):42 f(6):132 所以对于abcdef共有132种顺序 一:对于出栈的顺序 A:fedcbaB:dcbaef // abcd入栈,dcba依次出栈,e入栈,e出