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;
}