平面最近的点对求解-HDU1007

本文探讨了平面上寻找最近点对问题的有效算法。通过分析,提出了利用分治策略结合排序减枝的方法,将复杂度从O(n^2)降低至O(nlogn),并提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目链接。题目大意:给平面上的一堆点,求解最近的两个。这个问题最简单的写法肯定是对于每一个点暴力的扫一遍,然后记录最小的距离。这个复杂度是n^2的。稍微思考一下我们可能有这样的感觉,如果我把这些点按照x或者y排个序,那么最近的点是不是就是在该点的附近呢?甚至是相邻?这样我们只需要nlogn就可以解决这个问题。如果想到这里不进行深入的思考就去写代码,一测样例,还过了,交上去就wa了。为什么会wa?其实上边的那个想法已经接近答案了,但是存在很大的漏洞。为什么?即使排好序,最近的点也不一定是相邻的两个点,自己思考为啥。(因为还有y坐标啊,x的确实最小了,但是y就一定了)。

虽然上边的方法是错误的,但是给我们提供了一个很重要的思考的方向:我只要按照某一维度排好序之后那么最近的点一定是在这个点的附近(一般来说)。要么是左边,要么是右边。这样我们可以使用分而治之的思想,把那些可能成功的点先选出来,然后在选出来的这些点集中小范围的暴力。这样加了一个减支之后我们问题规模就会大大的减小,暴力就可以过了。代码如下:

#include<bits/stdc++.h>
using namespace std;
const double INF = 1e18;
const int maxn = 1e5 + 10;
struct P
{
	double x, y;
}pos[maxn],tem[maxn];
bool cmpxy(P&u, P&v)
{
	if (u.x != v.x)return u.x < v.x;
	else
	{
		return u.y < v.y;
	}
}
bool cmpy(P&u, P&v)
{
	return u.y < v.y;
}
double dis(P&u, P&v)
{
	return sqrt(pow((u.x - v.x), 2) + pow((u.y - v.y), 2));
}
double Close_P(int l, int r)
{
	double d = INF;
	if (l == r)return d;
	if (l + 1 == d)return  dis(pos[l], pos[r]);
	int mid = (l + r) >> 1;
	double d1 = Close_P(l, mid);
	double d2 = Close_P(mid + 1, r);
	d = min(d1, d2);
	int k = 0;
        //这里进行筛选,为什么可以这样?因为我们已经知道最短的距离是d
        //那么只有在距离mid的横坐标<=d才有可能成立,否则一定不成立
	for (int i = l;i <= r; i++)
	{
		if (abs(pos[i].x - pos[mid].x) <= d)
		{
			tem[k++] = pos[i];
		}
	}
	//按照y排序
	sort(tem, tem + k, cmpy);
	for (int i = 0; i < k; i++)
	{
                //这里减支的原理和上边是一个道理
		for (int j = i + 1; j < k&&tem[j].y - tem[i].y < d; j++)
		{
			d = min(d, dis(tem[i], tem[j]));
		}
	}
	return d;
}
int main()
{

	int n;
	P p;
	while (cin >> n && n)
	{
		for (int i = 0; i < n; +i++)
		{
			scanf("%lf%lf", &pos[i].x, &pos[i].y);
		}
		sort(pos, pos + n, cmpxy);

		printf("%.2lf\n", Close_P(0, n - 1) / 2);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值