最近点对问题

  最近点对问题,是分治法的一个典型应用,可以作为分治法入门的一个切入点。

  最近点对问题的描述比较简单,在二维平面中,给定一堆点,求距离最近的一对点,思路是,讲这一堆点分为两部分,左域与右域,如何划分左域右域呢?我们知道,这一堆点,每一个点都有其横坐标,假如有十个点,对应十个横坐标,我们就取其中间数,然后分别对其左右域求最小值,关于如何对左右域求最小值问题上,别人采用的一般都是类似于快速排序的递归模型,我这里采用的是DFS方法来对其进行递归,分别求得其左右域的最小值,我们求得左右域的最小值后,还要考虑一点,假设此时的最小值为X,然而还有一个可能,左域里面,最靠近分界线的一个点,和右域里面最靠近分界线的一个点,其距离小于X,这样最小距离就并非X了,所以,还要考虑一段以分界线为中位线,左右长度各位X/2的矩形面积里面,是否有一对点距离小于X,然后便可以找到其最近点对。


#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <cmath>  
#include <algorithm> 
using namespace std;
const int MAX=10000;
const int time=8;
float minLength=65535;

typedef struct 
{
  float x;
  float y;
}Node;
Node a[MAX]={{-10,1},{-4,1},{-2,2},{-0.2,1},{0.3,1},{1.5,3},{3,1},{4,1}};
bool cmp(const Node &a,const Node & b )
{
	if(a.x!=b.x)
		return a.x<b.x;
	return a.y<b.y;
}
float Length(int i,int j)
{
	return std::sqrt((a[j].y-a[i].y)*(a[j].y-a[i].y)+(a[j].x-a[i].x)*(a[j].x-a[i].x));
}

void ClosestPair(int start,int end)
{
   int  i;
   float len;
  if(start==end)
	  return;
  ClosestPair(start+1,end);
  for(i=start+1;i<=end;i++)
  {
    len=Length(start,i);
	minLength=min(minLength,len);
  }

}
void Solve()
{
   float mid;
   int temp[MAX];
   int i=0,k=0,j=0;
   mid=(a[time/2-1].x+a[time/2].x)/2;
   for(i=0;i<time;i++)
   {
	   if(fabs(a[i].x-mid) <minLength)
	   {
	      temp[k++]=i;
	   }
   }
   //temp record the points between the field in middle
   //k means the totla number in temp
   for(i=0;i<k-1;i++)
   {
      for(j=i+1;j<=k-1;j++)
	  {
		  minLength=min(minLength,Length(temp[i],temp[j]));
	  }
   }


}
int main()
{
	int i;
	/*for(i=0;i<time;i++)
	{
		cin>>a[i].x;
		cin>>a[i].y;
	}*/

	//输入完毕
	sort(a,a+time,cmp);
	ClosestPair(0,time/2-1);
	ClosestPair(time/2,time-1);
	//minLength为求得左右两个区间的最近点对的距离
	Solve();
	cout<<minLength<<endl;
 return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值