HDU 4347 - The Closest M Points - [KDTree模板题]
本文参考:
https://www.cnblogs.com/GerynOhenz/p/8727415.html
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4347
Problem Description
The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many points in K-dimensional space .Given a point. ZLC need to find out the closest m
points. Euclidean distance is used as the distance metric between two points. The Euclidean distance between points p and q is the length of the line segment connecting them.In Cartesian coordinates, if p =
(p1, p2,..., pn) and q = (q1, q2,..., qn) are two points in Euclidean n-space, then the distance from p to q, or from q to p is given by:
$d\left( {{\bf{p}},{\bf{q}}} \right) = d\left( {{\bf{q}},{\bf{p}}} \right) = \sqrt {\sum\limits_{i = 1}^n {\left( {p_i - q_i } \right)^2 } }$
Can you help him solve this problem?
Input
In the first line of the text file. There are two non-negative integers n and K. They denote respectively: the number of points, 1 <= n <= 50000, and the number of Dimensions, 1 <= K <= 5. In each of the following n lines there is written K integers, representing the coordinates of a point. This followed by a line with one positive integer t, representing the number of queries, 1 <= t <=10000.
Each query contains two lines. The k integers in the first line represent the given point. In the second line, there is one integer m, the number of closest points you should find,1 <= m <=10. The absolute value of all the coordinates will not be more than 10000. There are multiple test cases. Process to end of file.
Output
For each query, output m+1 lines:
The first line saying :”the closest m points are:” where m is the number of the points.
The following m lines representing m points ,in accordance with the order from near to far
It is guaranteed that the answer can only be formed in one ways. The distances from the given point to all the nearest m+1 points are different. That means input like this:
2 2
1 1
3 3
1
2 2
1
will not exist.
Sample Input
3 2
1 1
1 3
3 4
2
2 3
2
2 3
1
Sample Output
the closest 2 points are:
1 3
3 4
the closest 1 points are:
1 3
题意:
给出 $n$ 个 $K$ 维的点,又给出 $t$ 个查询, 每个查询也给出一个 $K$ 维的点,要求查询 $n$ 个点中距离这个点最近的 $M$ 个点。
题解:
KDTree模板题。
以下关于KDTree的小记:
1、简介
KDTree(K-dimensional tree) 是一个支持多维空间的数据结构,主要是将空间内的点进行区域划分,快速维护有关空间点的操作,例如空间的最远(近)点对,区间搜索。
KDTree 的结构与线段树类似,只是线段树是对一维空间的操作,而 KDTree 是多维操作的,这也导致了 KDTree 的灵活性没有线段树高。
树上每个节点所维护的信息:
- 左右两个儿子
- 该点表示的空间范围(超长方体,当 $K=2$ 时为矩形,$K=3$ 时为长方体)
- 中位点(坐标等信息)
2.1、建树
假设我们已经有了一个描述 $K$ 维空间内的点的类Point,且我们已经有Point类型的 $a[0:n-1]$ 数组。
首先因为是空间划分,所以要循环递进地用垂直于各维度轴的超平面(或者线、平面)进行划分。
例如在二维平面上的划分,先用垂直 $x$ 轴的直线进行划分,再用垂直 $y$ 轴的直线进行划分,再用垂直 $x$ 轴的直线进行划分……
那么,假设现在要用垂直 $x$ 轴的直线划分在 $a[0:n-1]$ 数组内某个整数区间 $[l,r)$ 上的这些点,
首先初始化该点的空间范围,假设 $mid = \left\lfloor {\frac{{l + r}}{2}} \right\rfloor$,作为 $[l,r)$ 按 $x$ 坐标从小到大排序时的中位点位置,
然后用 nth_element(st,st+n,ed) 线性时间复杂度地将 $[l,r)$ 分成了 $[l,mid)$ 和 $[mid+1,r)$ 两部分,而 $a[mid]$ 则存储了中位点,
然后递归两个区间(作为左右儿子),当然,这两个区间则要用垂直 $y$ 轴的直线进行划分,以此类推。
(其中,调用 nth_element(st,st+n,ed) 方法可以求得 $[st,ed)$ 区间内所有元素中第 $n$ 小的元素,并把它放在第 $n$ 个位置上。注意,下标是从 $st+0$ 开始计数的,也就是说求第 $0$ 小的元素就是最小的数,同样地,第 $0$ 个位置是最前面的位置。)
举例:
2.2、查询 $k$ 近邻
$k$ 近邻是指找到第 $k$ 近的点,需要维护一个大顶堆,维护当前 $k$ 个点中的最远距离,如果当前点比最远距离要小,则更新大根堆,而且利用最远距离可以减掉那些不在当前第 $k$ 距离内的区间。
AC代码:
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std; const int maxn=5e4+;
const int maxk=;
int k,idx;
struct Point
{
int x[maxk];
bool operator<(const Point &o)const
{
return x[idx]<o.x[idx];
}
void print()
{
for(int i=;i<k;i++) printf("%d%c",x[i],(i==k-)?'\n':' ');
}
}poi[maxn];
typedef pair<double,Point> P;
priority_queue<P> Q;
void clear(priority_queue<P> &Q)
{
if(Q.empty()) return;
priority_queue<P> tp;
swap(Q,tp);
}
struct kdTree
{
#define sqr(x) ((x)*(x))
#define ls (rt<<1)
#define rs (rt<<1|1)
Point o[maxn<<];
int son[maxn<<]; void build(int rt,int l,int r,int dep)
{
if(l>r) return;
son[rt]=r-l, son[ls]=son[rs]=-;
idx=dep%k;
int mid=(l+r)>>;
nth_element(poi+l,poi+mid,poi+r+);
o[rt]=poi[mid];
build(ls,l,mid-,dep+);
build(rs,mid+,r,dep+);
}
void query(int rt,Point p,int m,int dep)
{
if(son[rt]==-) return;
P nd(,o[rt]);
for(int i=;i<k;i++) nd.fi+=sqr(nd.se.x[i]-p.x[i]);
int dim=dep%k, x=ls, y=rs; bool fg=;
if(p.x[dim]>=o[rt].x[dim]) swap(x,y);
if(~son[x]) query(x,p,m,dep+);
if(Q.size()<m) Q.push(nd), fg=;
else
{
if(nd.fi<Q.top().fi) Q.pop(), Q.push(nd);
if(sqr(p.x[dim]-o[rt].x[dim])<Q.top().fi) fg=;
}
if(~son[y] && fg) query(y,p,m,dep+);
}
}kdt; int n;
int main()
{
while(cin>>n>>k)
{
for(int i=;i<n;i++) for(int j=;j<k;j++) scanf("%d",&(poi[i].x[j]));
kdt.build(,,n-,); int t; cin>>t;
stack<Point> ans;
while(t--)
{
Point qry;
for(int i=;i<k;i++) scanf("%d",&qry.x[i]);
int m; scanf("%d",&m); clear(Q);
kdt.query(,qry,m,); printf("the closest %d points are:\n",m);
while(Q.size()) ans.push(Q.top().se), Q.pop();
while(ans.size()) ans.top().print(), ans.pop();
}
}
}
HDU 4347 - The Closest M Points - [KDTree模板题]的更多相关文章
- bzoj 3053 HDU 4347 : The Closest M Points kd树
bzoj 3053 HDU 4347 : The Closest M Points kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差 ...
- hud 4347 The Closest M Points(KD-Tree)
传送门 解题思路 \(KD-Tree\)模板题,\(KD-Tree\)解决的是多维问题,它是一个可以储存\(K\)维数据的二叉树,每一层都被一维所分割.它的插入删除复杂度为\(log^2 n\),它查 ...
- HDU 4347 The Closest M Points (kdTree)
赤果果的kdTree. 学习传送门:http://www.cnblogs.com/v-July-v/archive/2012/11/20/3125419.html 其实就是二叉树的变形 #includ ...
- hdu 4347 The Closest M Points (kd树)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4347 题意: 求k维空间中离所给点最近的m个点,并按顺序输出 . 解法: kd树模板题 . 不懂kd树的可以先看看这个 . 不多说, ...
- 数据结构(KD树):HDU 4347 The Closest M Points
The Closest M Points Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Ot ...
- hdu 4347 The Closest M Points(KD树)
Problem - 4347 一道KNN的题.直接用kd树加上一个暴力更新就撸过去了.写的时候有一个错误就是搜索一边子树的时候返回有当前层数会被改变了,然后就直接判断搜索另一边子树,搞到wa了半天. ...
- 洛谷 P4148 简单题 KD-Tree 模板题
Code: //洛谷 P4148 简单题 KD-Tree 模板题 #include <cstdio> #include <algorithm> #include <cst ...
- hdu4347The Closest M Points kdtree
kdtree讲解: https://blog.csdn.net/qing101hua/article/details/53228668 https://blog.csdn.net/acdreamers ...
- 【HDOJ】4347 The Closest M Points
居然是KD解. /* 4347 */ #include <iostream> #include <sstream> #include <string> #inclu ...
随机推荐
- CSS3 选择器 基本选择器介绍
CSS是一种用于屏幕上渲染html,xml等一种语言,CSS主要是在相应的元素中应用样式,来渲染相对应用的元素,那么这样我们选择相应的元素就很重要了,如何选择对应的元素,此时就需要我们所说的选择器.选 ...
- lua -- 生成协议
这是爬塔的协议 <?xml version="1.0" encoding="utf-8" ?> <coder name="Tower ...
- npm WARN unmet dependency错误解决方法
在MAC上安装webpack以及reactjs等其它组件时,安装太慢卡住不动,直接ctrl+c终止后,再npm install后出npm WARN unmet dependency错误,npm cac ...
- vue条件与循环
通过vue控制切换一个元素的显示也相当简单: <div id="app-3"> <p v-if="seen">Now you see m ...
- Java知多少(21)this关键字详解
this 关键字用来表示当前对象本身,或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性.例如: public class Demo{ public int x = 10; publi ...
- 关于使用maven打包如何聚合资源文件
多数情况下,我们使用maven管理多个子工程,在最后maven打包阶段将多个子工程聚合到一个jar或war包.单个子工程会有自己独立的资源配置文件,在打包的时候我们需要将其聚合在一起(各子工程中的配置 ...
- Python3运算符
一.算术运算符 二.比较运算符 三 .赋值运算符 四 .位运算符 按位运算符是把数字看作二进制来进行计算的.Python中的按位运算法则如下: 下表中变量 a 为 60,b 为 13二进制格式如下: ...
- .NET中进行Base64加密解密
方法一: /// <summary> /// Base64加密 /// </summary> /// <param name="Message"> ...
- [Artoolkit] ARSimpleNativeCarsProj for Multi Markers Tracking
效果简直了,但代码架构有点坑,慢慢道来. libc++_shared.so应该是c++的库:libARWrapperNativeCaresExample.so也有对应的c++文件:那么,libARWr ...
- [Algorithm] Polynomial and FFT
排序:nlogn 二分查找:logn <-- 利用单调性,查n次,每次logn Multiply the following pairs of polynomials using at most ...