平面最近点对(分治)

题目描述

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

输入输出格式

输入格式:

第一行:n;2≤n≤200000

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

输出格式:

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

 1 //分治基础题
 2 #include<cmath>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<algorithm>
 7 using namespace std;
 8 int n,m,q,cnt;
 9 struct node{
10     int x;
11     int y;
12 }poi[200005],tmp[200005];
13 int cmp1(node a,node b){
14     if(a.x==b.x){
15         return a.y<a.y;
16     }
17     return a.x<b.x;
18 }
19 int cmp2(node a,node b){
20     return  a.y<b.y;
21 }
22 double cal(node a,node b){
23     long long x=1ll*abs(a.x-b.x)*abs(a.x-b.x);
24     long long y=1ll*abs(a.y-b.y)*abs(a.y-b.y);
25     return sqrt(x+y);
26 }
27 double solve(int l,int r){
28     double mn=0x3f3f3f3f;
29     if(l==r){
30         return mn;
31     }
32     if(l+1==r){
33         return cal(poi[l],poi[r]);
34     }
35     int mid=(l+r)>>1;
36     int tp=0;
37     double mnl=solve(l,mid);
38     double mnr=solve(mid+1,r);
39     mn=min(mnl,mnr);
40     for(int i=l;i<=r;i++){
41         if(abs(poi[i].x-poi[mid].x)<=mn)tmp[++tp]=poi[i];
42     }
43     sort(tmp+1,tmp+tp+1,cmp2);
44     for(int i=1;i<=tp;i++){
45         for(int j=1;j<=tp;j++){
46             if(i==j)continue;
47             if(abs(tmp[i].y-tmp[j].y)>mn)continue;
48             mn=min(mn,cal(tmp[i],tmp[j]));
49         }
50     }
51     return mn;
52 }
53 int main(){
54     scanf("%d",&n);
55     for(int i=1;i<=n;i++){
56         scanf("%d%d",&poi[i].x,&poi[i].y);
57     }
58     sort(poi+1,poi+n+1,cmp1);
59     double ans=solve(1,n);
60     printf("%.4lf",ans);
61     return 0;
62 }

原文地址:https://www.cnblogs.com/lnxcj/p/9915807.html

时间: 2024-10-26 04:27:47

平面最近点对(分治)的相关文章

平面最近点对(分治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

计算几何 平面最近点对 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=

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

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

牛客练习赛11 B trie树+拓扑判环 E 分治求平面最近点对

牛客练习赛11 B  假的字符串题意:给定n个字符串,互不相等,你可以任意指定字符之间的大小关系(即重定义字典序),求有多少个串可能成为字典序最小的串,并输出它们. tags:好题 对于一个字符串, 1]如有其它字符串是它的前缀,那肯定不可能.这个直接用字典树处理就可以. 2]但如果以这个字符串为最小,怎么判定其它字符串不会矛盾呢? 其实矛盾的情况详细一点说是: 比如要以  abcd 为最小, 但又有另一个字符串 aba ,这就矛盾了. 对这种情况,在跑字典树的时候,我们对有相同父亲结点的多个儿

分治 -- 平面最近点对

平面最近点对 : 分析各种情况 : 首先将所有点对按照 x 作为第一关键字进行排序,然后从中间进行劈开,进行递归分治 最后答案就是 res = min(l -- mid,mid + 1 -- r); 从上图可以得知 : 要求在这个平面内所有点中的最近点对,会有三种情况: 1.两个点都在左侧 2.两个点都在右侧 3.一个点在左侧,一个点在右侧 分别向两侧递归进行分治 : 寻找最近点对 : 1.找到左侧的最近点对 2.找到右侧的最近点对 进行比较我们就会得到一个左侧和右侧之中的最近的一对 这时我们会

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

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

$Poj3714/AcWing\ Raid$ 分治/平面最近点对

$AcWing$ $Sol$ 平面最近点对板子题,注意要求的是两种不同的点之间的距离. $Code$ #include<bits/stdc++.h> #define il inline #define Rg register #define go(i,a,b) for(Rg int i=a;i<=b;++i) #define yes(i,a,b) for(Rg int i=a;i>=b;--i) #define mem(a,b) memset(a,b,sizeof(a)) #def