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 ...
随机推荐
- ios实例开发精品源码文章推荐(8.22)
1.iOS源码:简单阅读器 http://www.apkbus.com/android-112176-1-1.html 2.iOS源码:音频声效--Audio Streamer<ignore_j ...
- 11G新特性 -- ASM的兼容性
Oracle 11g中,asm同时支持10g和11g数据库.但是asm的版本不能低于数据库的版本. 与兼容性现相关的两个参数: ·compatible.rdbms 支持的最低版本的oracle数据库版 ...
- 0x02 Spring Cloud 学习文档
每个Spring项目都有自己的; 它详细解释了如何使用项目功能以及使用它们可以实现的功能. Spring Cloud 版本 参考文档 API文档 Finchley SR2 CURRENT GA Ref ...
- 读取Excel二进制写入DB,并从DB中读取生成Excel文件
namespace SendMailSMSService { class Program { static void Main(string[] args) { var connString = Sq ...
- lua -- 所有UI组件的基类
-- 组件行为基础 local Behavior = class("Behavior"); function Behavior:ctor(name) self.owner = ni ...
- 每日英语:Upgrade Your Life: How to speed up your PC (or Mac)
Is your desktop or laptop computer starting to feel a little poky? Even after just a few months of u ...
- RxSwift之路 2#如何开始
RxSwift之路 2#如何开始 第一步当然是把项目clone到本地,github地址:https://github.com/ReactiveX/RxSwift. 官方文档 学习的第一手资源当然是项目 ...
- 8个非常个性化的CSS3单/复选框
单选框和复选框在网页表单中应用十分广泛,但是浏览器默认自带的单选框和复选框样式不仅不统一,而且大多都比较简单丑陋.本文给大家介绍了一些基于CSS3的个性化单选框和复选框,一些选中动画是基于jQuery ...
- Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配
/** 题目: Fixed Partition Memory Management UVALive - 2238 链接:https://vjudge.net/problem/UVALive-2238 ...
- CentOS系统实现SSH无密码登录的方法
一.环境配置 1.服务端:CentOS release 5.3 IP:222.73.115.198 2.客服端:CentOS release 5.8 IP:192.168.4.244 二.配置SSH无 ...