题目传送门

题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的。$n$<=100000。


$Algorithm$

最朴素的$n^2$枚举肯定是不行了,我们在这个数量级只能考虑$nlogn$做法。那么与这个数量级比较相关的也就是分治了。 把整个平面分为两个部分,分别求出两个部分点对间最小的距离,之后再处理跨区域的情况。

• 分治法求解步骤: O(NlogN)  by hzwer
1 将点集 S 分为两个⼦集 SL 和 SR 分别求解
2 记 δ 为⼦集中求得的最优值(min(δL; δR)),合并两个集合求
解。
图中以分界线为中⼼,任何⼀个 2δ · 2δ 的正⽅形内,只有常
数个点,暴⼒ for 过去就好了。


$Code$

 #include<cstdio>
#include<algorithm>
#include<cmath> using namespace std; int n;
int que[];
struct node{
double x,y;
}p[];
bool cmp(node a,node b)
{
return a.x<b.x;
} bool cmp2(int a,int b)
{
return p[a].y<p[b].y;
} double dis(int i,int j)
{
return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
} double merge(int l,int r)
{
double dd=1e8;
if(l==r) return dd;
if(l+==r) return dis(l,r);
int mid=(l+r)>>;
double dl=merge(l,mid);
double dr=merge(mid+,r);
dd=min(dl,dr); int pos=;
for(int i=l;i<=r;i++)
if(fabs(p[mid].x-p[i].x)<dd) que[++pos]=i;
sort(que+,que++pos,cmp2);
for(int i=;i<=pos;i++)
for(int j=i+;j<=pos;j++)
{
if(dis(que[i],que[j])>dd) break;
double ddd=dis(que[i],que[j]);
dd=min(dd,ddd);
}
return dd;
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p+,p++n,cmp);
printf("%.4lf",merge(,n));
return ;
}

几个注意事项

  • 边界的处理。
    if(l==r) return dd;
if(l+==r) return dis(l,r);
  • 利用正方形里有常数个点的性质时,要及时$break$。否则会超时。
  • 图中的$L$线大概是$mid$。开始找点的时候距离与他比较。

Luogu P1429 平面最近点对 【分治】By cellur925的更多相关文章

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

    P1429 平面最近点对(加强版) 题意 题目描述 给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的. 输入输出格式 输入格式: 第一行: ...

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

    Luogu 1429 平面最近点对 题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 ...

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

    P1429 平面最近点对(加强版) 主要思路: 分治,将点按横坐标为第1关键字升序排列,纵坐标为第2关键字升序排列,进入左半边和右半边进行分治. 设d为左右半边的最小点对值.然后以mid这个点为中心, ...

  4. 平面最近点对(分治nlogn)

    平面最近点对,是指给出平面上的n个点,寻找点对间的最小距离 首先可以对按照x为第一关键字排序,然后每次按照x进行分治,左边求出一个最短距离d1,右边也求出一个最短距离d2,那么取d=min(d1, d ...

  5. P1429 平面最近点对[加强版] 随机化

    LINK:平面最近点对 加强版 有一种分治的做法 因为按照x排序分治再按y排序 可以证明每次一个只会和周边的六个点进行更新. 好像不算很难 这里给出一种随机化的做法. 前置知识是旋转坐标系 即以某个点 ...

  6. 洛谷 P1429 平面最近点对(加强版) (分治模板题)

    题意:有\(n\)个点对,找到它们之间的最短距离. 题解:我们先对所有点对以\(x\)的大小进行排序,然后分治,每次左右二等分递归下去,当\(l+1=r\)的时候,我们计算一下距离直接返回给上一层,若 ...

  7. p1429 平面最近点对(加强版)

    传送门 分析 我们可以枚举每一个点算它的最近点 估价函数应该分为3种情况计算: 大于max,小于min,位于min和max之间 代码 #include<iostream> #include ...

  8. (洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714

    这个讲的好: https://phoenixzhao.github.io/%E6%B1%82%E6%9C%80%E8%BF%91%E5%AF%B9%E7%9A%84%E4%B8%89%E7%A7%8D ...

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

    题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y, ...

随机推荐

  1. TListView使用方法1(转)

    ListView1.Items 为标准 Tlistitems类 ListView1.Items (1)赋值 with ListView1.Items.Add do begin Caption:=cap ...

  2. C#压缩或解压(rar和zip文件)

    /// <summary> /// 解压RAR和ZIP文件(需存在Winrar.exe(只要自己电脑上可以解压或压缩文件就存在Winrar.exe)) /// </summary&g ...

  3. centos或者ubuntu设置ssh免密码登陆

    1. 输入  # ssh-keygen -t rsa -P ""  然后一路回车 2.输入  # cat ~/.ssh/id_rsa.pub >> ~/.ssh/aut ...

  4. (转)gcc学习笔记

    1.gcc -Wall hello.c -o hello //编译源文件,显示警告信息 2../a.out   //运行程序 3.gcc -Wall calc.c /usr/lib/libm.a -o ...

  5. 给EasyUi的Form加入自己主动填充部分输入框的方法

    依据项目须要,基于获取的数据对Form的部分输入框进行填充,而默认的EasyUI的Form 没有该方法.仅仅能一个输入框一个输入框的直接赋值,为此添加了Form对象的setValues,实现依据给定的 ...

  6. ie下文件上传无权访问的问题

    最近项目遇到个问题,ie下文件上传无权访问,在网上找了很久才找到答案,原来是因为ie下不能用js触发input=file的点击事件,必须手动点击才可以.

  7. 如何使用git 生成patch 和打入patch【转】

    本文转载自:http://blog.csdn.net/liuhaomatou/article/details/54410361 平时我们在使用git 管理项目的时候,会遇到这样一种情况,那就是客户使用 ...

  8. linux下lk和kernel层通信方式[2]

    U-Boot与Linux内核的交互 说明:本文所使用的U-Boot的版本是1.1.6,平台是S3C2440. 目录 一.简介 1.1标记列表二.设置标记存放的地址 2.1相关的结构体定义 2.2标记存 ...

  9. STL Algorithms 之 unique

    C++的文档中说,STL中的unique是类似于这样实现的: template <class ForwardIterator> ForwardIterator unique ( Forwa ...

  10. FTOUR2 - Free tour II

    传送门 题目翻译的很清楚……似乎点分治的题题目描述都非常简洁. 还是那个操作,一条路径要么全部在一棵子树中,要么经过当前的重心,所以考虑点分治. 首先dfs求出重心的每一棵子树中,有i个黑点的最长路径 ...