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


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

    题意

    题目描述

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

    输入输出格式

    输入格式:

    第一行:(n)(2leq nleq 200000)

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

    输出格式:

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

    输入输出样例

    输入样例#1:

    3
    1 1
    1 2
    2 2
    

    输出样例#1:

    1.0000
    

    说明

    (0leq x,yleq 10^9)

    思路

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

    首先通过分治,我们已经求出了左右两区间的最近点对距离(min),接下来找到([l,r])区间内横坐标与(mid)的横坐标相差不超过(min)的点,并将这些点两两匹配求出最近距离。这样能保证答案的正确性,但是时间复杂度呢?据说这样子做的时间复杂度是(O(nlog 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;
    }
    
  • 相关阅读:
    人脸开锁
    xtrabackup 8.0如何恢复单表
    这样配置,让你的VS Code好用到飞起!
    sqlserver安装教程(sql server2019安装详细步骤)
    史上最全vscode配置使用教程
    CxSAST 安装教程
    AppScan下载、安装、使用教程
    查看mysql数据库表结构注释信息
    从外包增删改查到大厂技术专家,我做对了什么?
    C内存操作API的实现原理
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9887177.html
Copyright © 2020-2023  润新知