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 ...
随机推荐
- mysql 5.5.x zip直接解压版 报1076
到官网下载mysql-5.5.10-win32.zip,然后将mysql解压到任意路径,如:C:\mysql-5.5.10-win32 打开计算机->属性->高级系统设置->环境变量 ...
- sed学习[参考转载]
一.选项与参数: -n :使用安静(silent)模式.在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上.但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者 ...
- mvc4 强大的导出和不需要上传文件的批量导入EXCEL--SNF快速开发平台3.1
数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,但在Web上我们应该如何实现呢?本文主要介绍利用MVC4+EasyUI的特点,并结合文件上传控件,实现文 ...
- [k8s]jenkins配合kubernetes插件实现k8s集群构建的持续集成
另一个结合harbor自动构建镜像的思路: 即code+baseimage一体的方案 - 程序员将代码提交到代码仓库gitlab - 钩子触发jenkins master启动一次构建 - jenkin ...
- Android Launcher分析和修改1——Launcher默认界面配置(default_workspace)
最近工作都在修改Launcher,所以打算把分析源码和修改源码的过程记录下来,最近会写一些关于Launcher的分析和修改博文.因为我是修改4.0.3的Launcher,所以后面文章里面的Launch ...
- 【iCore1S 双核心板_ARM】例程十一:RTC实时时钟实验——显示时间和日期
实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ RTC_DateTypeDef sDate; RTC_TimeTypeDef sTime; u ...
- 前端异常监控 - BadJS
前端异常监控 - BadJS 简介:BadJS 是 web 前端异常监控解决方案,提供一种 web 页面的脚本错误监控.上报.统计.查看等系统化的跟踪解决方案.目前BadJS覆盖了腾讯课堂.公众号.邮 ...
- Unity5 AssetBundle系列——资源加载卸载以及AssetBundleManifest的使用
下面代码列出了对于assetbundle资源的常用操作,其中有针对bundle.asset.gameobject三种类型对象的操作,实际使用中尽量保证成对使用. 这一块的操作比较繁琐,但只要使用正确, ...
- Asp.net Daily Build by MsBuild
:: 目录结构:: +GW.Point.BLL --dir dll:: +GW.Point.IBLL --dir dll:: +GW.Point.DAL --dir dll:: +GW.Point.I ...
- JSON 转JAVA代码
http://jsongen.byingtondesign.com/ http://pojo.sodhanalibrary.com/ http://www.jsonschema2pojo.org/