P1429 平面最近点对(加强版)

162 阅读2分钟

P1429 平面最近点对(加强版) 提交25.77k

通过7.95k

时间限制1.00s

内存限制256.00MB

提交答案加入题单

题目提供者洛谷

难度提高+/省选-

历史分数100

提交记录 查看题解

标签 查看算法标签

进入讨论版

相关讨论 查看讨论

推荐题目 查看推荐

洛谷推荐关闭

展开

题目背景 P7883 平面最近点对(加强加强版)

题目描述 给定平面上 nn 个点,找出其中的一对点的距离,使得在这 nn 个点的所有点对中,该距离为所有点对中最小的

输入格式 第一行:nn ,保证 2\le n\le 2000002≤n≤200000 。

接下来 nn 行:每行两个实数:x\ yx y ,表示一个点的行坐标和列坐标,中间用一个空格隔开。

输出格式 仅一行,一个实数,表示最短距离,精确到小数点后面 44 位。

输入输出样例 输入 #1复制

3 1 1 1 2 2 2 输出 #1复制

1.0000 说明/提示 数据保证 0\le x,y\le 10^90≤x,y≤109

#include<cstdio>
#include<cstring>
#include<cmath>
#include <iostream>
#include<stack>
#include<cstdlib>
#include<map>
#pragma warning(disable:4996)
using namespace std;
typedef long long ll;
//总结 本题中心思想  分治
//通过结构体排序可脑补出一个平面
//然后通过分治 分别得到左平面 右平面的最小值 初步得到答案
//但是需要注意的是中间的一些的点没比较
//把中间的那些点暴力求出 即可 然后 就可以得到最小值
struct Node
{
	double x;
	double y;
}p[200005];
int b[200005];
double getS(Node x, Node y)
{
	return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
}
int comp1(Node x, Node y)
{
	if (x.x == y.x)
	{
		return x.y < y.y;
	}
	return x.x < y.x;
}
int comp2(int x, int y)
{
	return p[x].y < p[y].y;
}
double run(int l, int r)
{
	if (l == r)//返回无穷大
	{
		return 1 << 31 - 1;
	}
	if (l + 1 == r)//返回两点距离
	{
		return getS(p[l], p[r]);
	}
	int mid = (l + r) >> 1;
	double d1 = run(l, mid);//左平面
	double d2 = run(mid + 1, r);//右平面
	double ans = min(d1, d2);//初步得到左右平面的最小值
	int i = 0;
	int k = 0;
	int j = 0;
	for (i = l; i <= r; i++)//暴力搜索可能比ans小的点
	{
		if (fabs(p[mid].x - p[i].x) <= ans)
		{
			b[++k] = i;
		}
	}
	sort(b + 1, b + 1 + k, comp2);//按y排序
	for (i = 1; i <= k; i++)
	{
		for (j = i + 1; j <= k && fabs(p[b[i]].y - p[b[j]].y) <= ans; j++)
		{
			
			double sum = getS(p[b[i]], p[b[j]]);
			ans = min(sum, ans);
		}
	}
	return ans;
}
int main()
{
	int n = 0;
	cin >> n;
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		cin >> p[i].x >> p[i].y;
	}
	sort(p + 1, p + 1 + n, comp1);//排序,看成一个平面
	printf("%.4lf", run(1, n));
	return 0;
}