HDU 1007-Quoit Design

点击打开题目链接

题目大意:给出二维平面上的n个点,求出其中最近的两个点的距离的一半。


解析:这道题首先想的是暴力枚举,然而n的范围是【0,100000】,使用暴力的话一定会超时的。

           然后想到分治法:将n个点按照x坐标排序,并将其分为左右两部分,分别求出其最小距离并合并。要注意,因为将所有点分成两部分了,所以没有考虑其中一点在左一点在右的情况。假设左右两部分的最短距离为d,则只要考虑【mid-d,mid+d】之间的点就可以了。在求此区间的最小值时,可以线将此区域的点按y坐标排序,分别比较(1,2)、(1,3)、……(1,m)(m<1+d)……、(2,3)、(2、4)、……、(2,m)(m-2<d)…….。

           ps:开始用cin、cout输入输出,一直超时,然后用scanf、printf就不超时了。


(代码注释写的比较清楚)下面是AC了的代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdio>
using namespace std;

//表示每个点的结构体
struct node
{
	double x,y;//(x,y)表示点的坐标
	int key;//点的编号
};
node ar[100005];//每个点的初始情况
node br[100005];//生成的d*2d矩形区域内的每个点的初始情况

int a,b;//表示距离最近的两个点的编号

//按x坐标比较两个点的大小
bool cmpx(node a,node b)
{
	return a.x<b.x;
}

//按y坐标比较两个点的大小
bool cmpy(node a,node b)
{
	return a.y<b.y;
}

//求两点之间的距离
double dis(node a,node b)
{
	return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}

//用分治法求最短距离
double dac(int s,int e)//所求区间的左右端点
{
	//递归终止条件:区间内只有一个点
	if(s==e) return 0x3f3f3f3f;

	int mid=(s+e)/2,tail=0;//区间终点、矩形带中点的个数
	double d=min(dac(s,mid),dac(mid+1,e));//分别求左右两边的最短距离

	//在d*2d矩形内可能有更小的距离
	//寻找左边矩形中的点
	for(int i=mid;i>=s&&ar[mid].x-ar[i].x<d;i--)
		br[tail++]=ar[i];

	//寻找右边矩形中的点
	for(int i=mid+1;i<e&&ar[i].x-ar[mid].x<d;i++)
		br[tail++]=ar[i];

	//对矩形内的点按y坐标排序
	sort(br,br+tail,cmpy);

	//计算矩形内任意左右两点的距离
	for(int i=0;i<tail;i++)
	{
		for(int j=i+1;j<tail&&br[j].y-br[i].y<d;j++)
		{
			//找到更小距离则更新结果
			if(d>dis(br[i],br[j]))
			{
				a=min(br[i].key,br[j].key);
				b=max(br[i].key,br[j].key);
				d=dis(br[i],br[j]);
			}
		}
	}

	return d;
}
int main()
{
	int n;
	while(cin>>n&&n)//当前组输入点的个数为n
	{
		for(int i=0;i<n;i++)//输入n个点
		{
			scanf("%lf%lf",&ar[i].x,&ar[i].y);
			ar[i].key=i+1;//当前点的编号
		}

		//按x坐标对所有点排序
		sort(ar,ar+n,cmpx);
		//调用分治函数求最小值
		printf("%.2f\n",dac(0,n)/2);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值