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

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

题意

题目描述

给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的。

输入输出格式

输入格式:

第一行:\(n\);\(2\leq n\leq 200000\)

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

输出格式:

仅一行,一个实数,表示最短距离,精确到小数点后面\(4\)位。

输入输出样例

输入样例#1:

3
1 1
1 2
2 2

输出样例#1:

1.0000

说明

\(0\leq x,y\leq 10^9\)

思路

利用分治的方法实现。我们先把所有点按照横坐标排序,然后查询每一个区间的最近点对距离。假设当前查询的是\([l,r]\)区间的最近点对距离,那么这个区间的答案就在\([l,mid]\)区间的最近点对距离、\([mid+1,r]\)区间的最近点对距离、靠近中间的分别在两个区间中的一些点之间的距离中产生,我们主要考虑第三部分答案如何统计。

首先通过分治,我们已经求出了左右两区间的最近点对距离\(min\),接下来找到\([l,r]\)区间内横坐标与\(mid\)的横坐标相差不超过\(min\)的点,并将这些点两两匹配求出最近距离。这样能保证答案的正确性,但是时间复杂度呢?据说这样子做的时间复杂度是\(O(n\log n)\)的,所以也不用担心超时的问题。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n;
struct Point
{
    double x,y;
    bool operator < (const Point &sjf){return x<sjf.x;}
}p[200005],q[200005];
double devide(int l,int r)
{
    if(l==r) return DBL_MAX;
    else if(l+1==r) return sqrt((p[l].x-p[r].x)*(p[l].x-p[r].x)+(p[l].y-p[r].y)*(p[l].y-p[r].y));
    int mid=(l+r)>>1,cnt=0;
    double d=min(devide(l,mid),devide(mid+1,r));
    for(int i=l;i<=r;i++) if(fabs(p[i].x-p[mid].x)<=d) q[++cnt]=p[i];
    for(int i=1;i<=cnt;i++)
        for(int j=i+1;j<=cnt&&fabs(q[i].x-q[j].x)<=d;j++)
            d=min(d,sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y)));
    return d;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
    sort(p+1,p+n+1);
    printf("%.4f",devide(1,n));
    return 0;
}

原文地址:https://www.cnblogs.com/coder-Uranus/p/9887177.html

时间: 2024-10-10 12:43:45

Luogu P1429 平面最近点对(加强版)的相关文章

Luogu P1429 平面最近点对 【分治】By cellur925

题目传送门 题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.$n$<=100000. $Algorithm$ 最朴素的$n^2$枚举肯定是不行了,我们在这个数量级只能考虑$nlogn$做法.那么与这个数量级比较相关的也就是分治了. 把整个平面分为两个部分,分别求出两个部分点对间最小的距离,之后再处理跨区域的情况. ? 分治法求解步骤: O(NlogN)  by hzwer1 将点集 S 分为两个?集 SL 和 SR 分别求解2 记 δ 为

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

P1429 平面最近点对(加强版) 主要思路: 分治,将点按横坐标为第1关键字升序排列,纵坐标为第2关键字升序排列,进入左半边和右半边进行分治. 设d为左右半边的最小点对值.然后以mid这个点为中心,扩展宽为2d,长为2d的正方形.除了这个正方形外的点都不可能使答案更小.而且这个正方形里至多8个点(可以证明至多6个,我不会.but,知道至多8个就够了,这样已经保证了复杂度.)一句话证明:如果多余8个点,那么必有2个点的最小距离比d小.这8个点内暴力枚举就好了. //luoguP1429 #inc

Luogu 1429 平面最近点对 | 平面分治

Luogu 1429 平面最近点对 题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开. 输出格式: 仅一行,一个实数,表示最短距离,精确到小数点后面4位. 这是一道平面上的分治. 这是一个平面,我们把它分成两半,使x坐标位于最中间的两个点分到左右两侧: 对于同在左侧或同在右侧的点对,我们可以递归处理:

「LuoguP1429」 平面最近点对(加强版)

题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开. 输出格式: 仅一行,一个实数,表示最短距离,精确到小数点后面4位. 输入输出样例 输入样例#1: 复制 3 1 1 1 2 2 2 输出样例#1: 复制 1.0000 说明 0<=x,y<=10^9 题解 考场清晰的记得以前听过,并且记错做法还觉得

hdu1007 平面最近点对(暴力+双线程优化)

突发奇想,用双线程似乎可以优化一些暴力 比如说平面最近点对这个题目,把点复制成2份 一份按照x排序,一份按照y排序 然后双线程暴力处理,一份处理x,一份处理y 如果数据利用x递减来卡,那么由于双线程,它卡不住y 如果数据利用y递减来卡,那么卡不住x 这样暴力n^2就可以过了 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algori

平面最近点对(分治nlogn)

平面最近点对,是指给出平面上的n个点,寻找点对间的最小距离 首先可以对按照x为第一关键字排序,然后每次按照x进行分治,左边求出一个最短距离d1,右边也求出一个最短距离d2,那么取d=min(d1, d2) 然后只需考虑横跨左右两侧的点,不妨枚举左侧的点pi 那么很显然的是如果pi距离中间的点超过了d,便可以直接舍去,只需考虑距离中间点小于d的点 这样一来就可以对每个pi画一个边长为2d的正方形,易证,矩形内最多存在8个点. 那么关键问题就是要快速找这8个点 朴素做法是对分治后的点进行快排,这样复

POJ 3714 Raid(平面最近点对)

解题思路: 分治法求平面最近点对,点分成两部分,加个标记就好了. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <iomanip>

平面最近点对

HDU 1007 求平面最近点对距离的一半 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const double eps = 1e-7; const int MAXN = 100010; const double INF = 1e20; struct Point

分治法二(平面最近点对)

上篇文章介绍了分治法的概念和基本解题步骤,并附加了一个例题帮助大家了解分治法的基本思想,在这篇文章中,我将对分治法的另一个经典问题进行分析,希望我的文章能够将今天的主题解释清楚.接下来我将用三种不同的方法求解"平面最近点对"问题. 问题描述:在一个平面上随机分布着 n 个点,现给定 n 个点的坐标,要求给出最近的两个点之间的距离. 方法一:原始方法 题目要求求出最近的两点之间的距离,先整理一下已知的线索:首先点的总个数为 n :其次已知 n 个点的坐标.掌握了每个点的坐标,就相当于间接