算法导论-分治法-最近点对-HDOJ1007

原创 2014年03月20日 10:38:51

HDOJ1007的原题目是求出在不同时套中两个玩具的前提下,圆圈的最大半径。问题翻译过来就是求解最近点对的问题,这个问题是经典的分治法问题。

参考博客:http://www.cnblogs.com/peng-come-on/archive/2012/01/18/2325163.html

毫无疑问,通过暴力手段列举所有的点对并计算这些点对的距离,找出最小的一组,可以得到最后的结果。但是,这道题的数据规模非常大,所以,这种传统的方法肯定行不通。我试过,hdoj是超时的。

我对原博客的第3步和第4步有不同的看法。

原博客步骤:

1.读取数据,并将点按横坐标升序排列。
2.以最中间的那个点为基准,将平面内的点分为左右两个部分。递归调用mindis(int,int)函数,分别求出左右两个部分的点集的最短距离,并取两者中的较小值,即为min.
3.显然,min并不一定是最短距离,因为还可能存在一种情况,即点对中的一个点位于左区域,另一个点位于右区域。所以,我们取点集中横坐标与分界线的距离小于min的点,存入p2[N]数组中。
4.对p2[N]数组中的点按纵坐标进行排序,计算p2[N]数组中的点对的距离,如果存在小于min 的情况,就取代min作为最近距离。
最后,min即为平面内点集的最近距离。

我的步骤是:

1.读取数据,并将点按横坐标升序排列。
2.以最中间的那个点为基准,将平面内的点分为左右两个部分。递归调用mindis(int,int)函数,分别求出左右两个部分的点集的最短距离,并取两者中的较小值,即为min.
3.显然,min并不一定是最短距离,因为还可能存在一种情况,即点对中的一个点位于左区域,另一个点位于右区域。所以,我们取点集中横坐标与分界线的距离小于min的点,根据在分界线的左右,分别存入pxSmall[N]数组和pxLarge[N]数组中。

4.因为唯一可能的情况是一个点在pxSmall[N],另一个点在pxLarge[N]中。只要遍历这个两个数组便可以了。

下面是在原博客代码上的修改:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

#define N 1000010

struct point 
{
 double x;
 double y;
}p1[N],pxSmall[N],pxLarge[N];

double dis ( point a , point b )
{
	return sqrt( pow (a.x-b.x,2) + pow ( a.y-b.y,2 ) );
}

double min ( double a , double b )
{
	return a<b?a:b;
}

bool cpx ( point a , point b )
{
	return a.x < b.x ;
}
bool cpy ( point a , point b )
{
	return a.y < b.y ;
}

double mindis (int l, int r)
{
	if( l + 1 == r )
		return dis ( p1[l] ,p1[r] );
	if( l + 2 == r )
		return min ( dis ( p1[l] , p1[l+1] ) , min ( dis ( p1[l+1] , p1[r] ) , dis ( p1[l] , p1[r] ) ) );
	else
	{
		int mid ,count1=0, count2=0;
		double mini;
		mid = ( l + r) >> 1 ;
		mini = min ( mindis ( l , mid ) , mindis ( mid+1 , r ) );
		for( int i = l ; i <= r ; i++ )
		{
			if ( fabs ( p1[i].x - p1[mid].x ) <= mini )
			{
				if (p1[i].x-p1[mid].x < 0)
					pxSmall[count1++]=p1[i];
				else
					pxLarge[count2++]=p1[i];
			}
				
		}
		//直接遍历两个数组
		for(int i=0;i<count1;i++)
		{
			for(int j=0;j<count2;j++)
			{
				double temp = dis(pxSmall[i], pxLarge[j]); 
				if(temp<mini)
					mini=temp;
			}
		}
		/*
		sort ( p2 , p2+count , cpy );
		for ( int i=0 ; i < count ; i++ )
		{
			for ( int j = i+1; j < count ;j++)
			{
				if ( p2[j].y-p2[i].y>=mini)
					break;
				else if(dis (p2[j],p2[i])<mini)
					mini=dis(p2[j],p2[i]);
			}
		}
		*/
		return mini;
	}
}
  
  

int main()
{
 //freopen("input.txt","r",stdin);
	int n ;
	double dia ;
	while(scanf("%d",&n)==1&&n)
	{
		for(int i=0;i<n;i++)
		scanf("%lf%lf",&p1[i].x,&p1[i].y);
		sort ( p1 , p1 + n-1 , cpx );
		dia = mindis ( 0 , n-1 );
		printf("%.2f\n", dia / 2 );
	}
	return 0;
}

我在HDOJ上分别跑这两组代码,发现原博客runtime为1875ms,我的代码runtime为1093ms,比原博客的运行时间少了很多。因为少了排序这个步骤。当然,可能不同的数据集得到的运行时间不同,如果换一个数据集或数据集规模很大的时候原博客的方法可能更有优势。但是有一点,我的方法更好地符合分治法的要求,正确性是可以保证的。最近一直在学习《算法导论》,这本书真是神书,是算法中的算法,不仅仅告诉你算法,还会告诉你算法的证明。以后如果遇到分治法的问题,我会继续补充到这篇博客。

补充:参考博客:http://blog.csdn.net/junerfsoft/article/details/2975495

博客中提到了飞机调度的问题,说的很好。可惜因为每个点的坐标类型都是double类型的,不能直接找到那6个点,可以使用二分查找,但是也不是特别方便。我随便写了代码,时间上反而更长了。

相关文章推荐

分治算法求最近点对

http://acm.hdu.edu.cn/showproblem.php?pid=1007          先说下题意,很简单,给n个点的坐标,求距离最近的一对点之间距离的一半。第一行是一个...

0007算法笔记——【分治法】最接近点对问题

问题场景:在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其他几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的一个点来看...

Java实现算法导论中最近点对问题分治法

最近点对问题:给定平面上的N个点,找出距离最近的两个点。分治法:              1 )如果数组长度(即点的个数,一般≤3)在一定范围内时直接求出最近点,蛮力求解,递归退出条件;    ...

HDU 1007 Quoit Design(分治法求最近点对问题)

本题的大致题意,求出最近两个点的距离的一半。 首先先看数据范围,如果暴力的话肯定会超时的,所以要想一个优化点的方法,就是对其进行分治。大致思路:先把一个大区间分为两个小区间,然后分别对两个区间进行排...

010-最近点对问题-分治法-《算法设计技巧与分析》M.H.A学习笔记

设S是平面上n个点的集合,在S中找到两点p、q,使得他们的欧几里得距离d(p,q)是所有点对中最小的。 朴素的算法是计算所有点对的距离,在求出最小的,需要Ω(n2)。 采用分治法可以在Θ(nlogn)...

分治法最近点对问题

在二维平面上的n个点中,如何快速的找出最近的一对点,就是最近点对问题。     一种简单的想法是暴力枚举每两个点,记录最小距离,显然,时间复杂度为O(n^2)。     在这里介绍一种时间...

分治法求最近点对

Implement the algorithm for the closest pair problem in your favorite language. INPUT: Given n poin...

分治法求最近点对

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

求最近点对算法分析

问题描述:     在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其他几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法导论-分治法-最近点对-HDOJ1007
举报原因:
原因补充:

(最多只允许输入30个字)