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

题目传送门

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



$Algorithm$

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

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



$Code$

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4
 5 using namespace std;
 6
 7 int n;
 8 int que[200090];
 9 struct node{
10     double x,y;
11 }p[200090];
12 bool cmp(node a,node b)
13 {
14     return a.x<b.x;
15 }
16
17 bool cmp2(int a,int b)
18 {
19     return p[a].y<p[b].y;
20 }
21
22 double dis(int i,int j)
23 {
24     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));
25 }
26
27 double merge(int l,int r)
28 {
29     double dd=1e8;
30     if(l==r) return dd;
31     if(l+1==r) return dis(l,r);
32     int mid=(l+r)>>1;
33     double dl=merge(l,mid);
34     double dr=merge(mid+1,r);
35     dd=min(dl,dr);
36
37     int pos=0;
38     for(int i=l;i<=r;i++)
39         if(fabs(p[mid].x-p[i].x)<dd) que[++pos]=i;
40     sort(que+1,que+1+pos,cmp2);
41     for(int i=1;i<=pos;i++)
42         for(int j=i+1;j<=pos;j++)
43         {
44             if(dis(que[i],que[j])>dd) break;
45             double ddd=dis(que[i],que[j]);
46             dd=min(dd,ddd);
47         }
48     return dd;
49 }
50
51 int main()
52 {
53     scanf("%d",&n);
54     for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
55     sort(p+1,p+1+n,cmp);
56     printf("%.4lf",merge(1,n));
57     return 0;
58 }

几个注意事项

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

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9737687.html

时间: 2024-11-12 09:13:40

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

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

P1429 平面最近点对(加强版) 题意 题目描述 给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的. 输入输出格式 输入格式: 第一行:\(n\):\(2\leq n\leq 200000\) 接下来\(n\)行:每行两个实数:\(x\ y\),表示一个点的行坐标和列坐标,中间用一个空格隔开. 输出格式: 仅一行,一个实数,表示最短距离,精确到小数点后面\(4\)位. 输入输出样例 输入样例#1: 3 1 1 1 2 2 2 输出样

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

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

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

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

平面最近点对(分治nlogn)

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

【HDU5721 BestCoder 2nd AnniversaryD】【平面最近点对 分治写法+KD-tree写法】Palace 平面最近点对

Palace Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 260    Accepted Submission(s): 72 Problem Description The last trial Venus imposes on Psyche is a quest to the underworld. She is to tak

HDU 5721 Palace BestCoder 2nd Anniversary (平面最近点对)

Palace Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 465    Accepted Submission(s): 118 Problem Description The last trial Venus imposes on Psyche is a quest to the underworld. She is to ta

「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 题解 考场清晰的记得以前听过,并且记错做法还觉得

计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点

平面最近点对,即平面中距离最近的两点 分治算法: int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对 { double ans; //answer 0)    调用前的预处理:对所有点排序,以x为第一关键词y为第二关键字 , 从小到大; 1)    将所有点按x坐标分成左右两部分; /*      分析当前集合[left,right]中的最近点对,有两种可能: 1. 当前集合中的最近点对,点对的两点同属于集合[left,mid]或同属

平面最近点对问题(分治)

平面最近点对问题是指:在给出的同一个平面内的所有点的坐标,然后找出这些点中最近的两个点的距离. 方法1:穷举 1)算法描述:已知集合S中有n个点,一共可以组成n(n-1)/2对点对,蛮力法就是对这n(n-1)/2对点对逐对进行距离计算,通过循环求得点集中的最近点对2)算法时间复杂度:算法一共要执行 n(n-1)/2次循环,因此算法复杂度为O(n2) 代码实现: 利用两个for循环可实现所有点的配对,每次配对算出距离然后更新最短距离. for (i=0 ; i < n ;i ++){ for(j=