kd树解平面最近点对

早上起来头有点疼,突然就想到能不能用kd树解平面最近点对问题,就找了道题试了一下,结果可以,虽然效率不高,但还是AC了~

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007

题目要求平面上最近点对间距离的一半。

思路如下:先建立一棵树,所有点插入树中,之后为每个点查询其最近点,枚举找到最小值。注意查询的时候不要让点自己跟自己比。个人感觉,这种写法也可以达到O(nlogn)的复杂度。建树分区间的时候,按x,y中跨度大的一个来分,应该就接近O(nlogn)了,不过我太懒了,那种方法之后再试,现在先x,y轮流着来了。

kd树代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 #include <cstdio>
 6 #include <cmath>
 7 #define MAX (101000)
 8 #define pow(x) ((x)*(x))
 9
10 using namespace std;
11
12 int n, idx;
13
14 struct Point{
15     double x[2];
16     bool operator < (const Point &u) const{
17         return x[idx] < u.x[idx];
18     }
19 }po[MAX];
20
21 struct Tree {
22     Point p[MAX<<2];
23     int son[MAX<<2];
24     bool f[MAX<<2];
25     int ps[MAX<<2];
26     void build ( int l , int r , int u = 1, int dep = 0)
27     {
28         if(l > r) return;
29         son[u] = r-l;
30         son[u<<1] = son[u<<1|1] = -1;
31         idx = dep%2;
32         int mid = (l+r)>>1;
33         nth_element(po+l, po+mid, po+r+1);
34         p[u] = po[mid], ps[u] = mid;
35         build ( l , mid-1 , u<<1 , dep+1 );
36         build ( mid+1 , r , u<<1|1 , dep+1 );
37     }
38
39     double query(Point a, int id, int u = 1, int dep = 0){
40         if(son[u] == -1) return 1000000000.0;
41
42         double dis = pow(p[u].x[0]-a.x[0]) + pow(p[u].x[1]-a.x[1]);
43         if(ps[u] == id) dis = 1000000000.0;
44         int dim = dep%2, fg = 0;
45         int x = u<<1, y = u<<1|1;
46         if(a.x[dim] >= p[u].x[dim]) swap(x, y);
47         double tm1 = 1000000000.0, tm2 = 1000000000.0;
48         if(~son[x])tm1 = query(a, id, x, dep+1);
49         if(pow(a.x[dim] - p[u].x[dim]) < tm1) fg = 1;
50         if(~son[y] && fg) tm2 = query(a, id, y, dep+1);
51         if(dis > tm1) dis = tm1;
52         if(dis > tm2) dis = tm2;
53         return dis;
54     }
55 }kd;
56
57
58 int main(){
59     while(~scanf("%d", &n), n){
60         for(int i = 0; i < n; i++)
61                 scanf("%lf %lf", &po[i].x[0], &po[i].x[1]);
62         memset(kd.f, 0, sizeof(kd.f));
63         memset(kd.ps, -1, sizeof(kd.ps));
64         kd.build(0, n-1);
65         double ans = 1000000000.0;
66         for(int i = 0; i < n; i++){
67             double tm = kd.query(po[i], i);
68             if(tm < ans) ans = tm;
69         }
70         printf("%.2lf\n", sqrt(ans)/2);
71     }
72     return 0;
73 }
时间: 2024-10-22 19:19:15

kd树解平面最近点对的相关文章

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

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

KNN算法与Kd树

最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知样本的类别,以全部训练样本作为代表点,计算未知样本与所有训练样本的距离,并以最近邻者的类别作为决策未知样本类别的唯一依据.但是,最近邻算法明显是存在缺陷的,比如下面的例子:有一个未知形状(图中绿色的圆点),如何判断它是什么形状? 显然,最近邻算法的缺陷--对噪声数据过于敏感,为了解决这个问题,我们可

02-17 kd树

目录 kd树 一.kd树学习目标 二.kd树引入 三.kd树详解 3.1 构造kd树 3.1.1 示例 3.2 kd树搜索 3.2.1 示例 四.kd树流程 4.1 输入 4.2 输出 4.3 流程 五.kd树优缺点 5.1 优点 5.2 缺点 六.小结 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬虫.人工智能教学等着你:https://www.cnblogs.com/nickchen121/ kd树 k近邻算法中讲到它有一个较为致命的缺点就是每个实例到未来新

从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章待写:1.KD树:2.神经网络:3.编程艺术第28章.你看到,blog内的文章与你于别处所见的任何都不同.于是,等啊等,等一台电脑,只好等待..”.得益于田,借了我一台电脑(借他电脑的时候,我连表示感谢,他说“能找到工作全靠你的博客,这点儿小忙还说,不地道”,有的时候,稍许感受到受人信任也是一种压力,愿我不辜负大家对我的信任)

多维空间分割树--KD树

算法介绍 KD树的全称为k-Dimension Tree的简称,是一种分割K维空间的数据结构,主要应用于关键信息的搜索.为什么说是K维的呢,因为这时候的空间不仅仅是2维度的,他可能是3维,4维度的或者是更多.我们举个例子,如果是二维的空间,对于其中的空间进行分割的就是一条条的分割线,比如说下面这个样子. 如果是3维的呢,那么分割的媒介就是一个平面了,下面是3维空间的分割 这就稍稍有点抽象了,如果是3维以上,我们把这样的分割媒介可以统统叫做超平面 .那么KD树算法有什么特别之处呢,还有他与K-NN

平面最近点对(分治nlogn)

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

2016 ICPC青岛站---k题 Finding Hotels(K-D树)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over the world. Each hotel has a location and a price. M guests want to find a hotel with an acceptable price and a minimum distance from their locations.

【特征匹配】SIFT原理之KD树+BBF算法解析

继上一篇中已经介绍了SIFT原理点击打开链接,最后得到了一系列特征点,每个特征点对应一个128维向量.假如现在有两副图片都已经提取到特征点,现在要做的就是匹配上相似的特征点. 相似性查询有两种基本方式:1.范围查询:即给点查询点和查询阈值,从数据集中找出所有与查询点距离小于阈值的点. 2.K近邻查询:给点查询点及正整数K,从数据集中找到与查询点最近的K个数据,当K=1时,就是最近邻查询. 特征匹配算子可以分为两类:1.穷举法:即将数据集中的点与查询点逐一计算距离,如果图1提取到N1个特征点,图2

KD树

什么是KD树 Kd-树是K-dimension tree的缩写,是对数据点在k维空间(如二维(x,y),三维(x,y,z),k维(x,y,z..))中划分的一种数据结构,主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索).本质上说,Kd-树就是一种平衡二叉树. 首先必须搞清楚的是,k-d树是一种空间划分树,说白了,就是把整个空间划分为特定的几个部分,然后在特定空间的部分内进行相关搜索操作.想像一个三维空间,kd树按照一定的划分规则把这个三维空间划分了多个空间,如下图所示: KD树的构建