刚开始学习,介绍先搁着~等理解透彻了再来写~~~
我是学习的mzry1992(UESTC_Izayoi ~)------http://www.mzry1992.com/blog/miao/kd%E6%A0%91.html
先去看mzry1992大牛博客里的讲解吧。。。
再附两篇论文:(看英文看得好爽。。。~@.@)
《An intoductory tutorial on kd-trees》 ★(里面就介绍了kd-tree和nearest neighbour algorithm(最近邻算法)、Q nearest neighbour(Q近邻))
《Range Searching Using Kd-Tree.》
kd-tree入门题:
HDOJ 2966 In case of failure (最近邻,模板~)
查找平面点最近点的距离(此题中是距离的平方)
/*
HDOJ 2966
KD-Tree模板
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x, y) ( (x + y)>>1 )
using namespace std;
typedef long long LL;
//KD-Tree模板
const int N=100005;
LL res;
struct Point
{
int x, y; //点是二维的,此时是2D-Tree
};
LL dist2(const Point &a, const Point &b) //距离的平方
{
return LL(a.x - b.x) * LL(a.x - b.x) + LL(a.y - b.y) * LL(a.y - b.y);
}
bool cmpX(const Point &a, const Point &b)
{
return a.x r) return;
int mid=MID(l, r);
int minX, minY, maxX, maxY;
minX = min_element(p + l, p + r + 1, cmpX)->x;
minY = min_element(p + l, p + r + 1, cmpY)->y;
maxX = max_element(p + l, p + r + 1, cmpX)->x;
maxY = max_element(p + l, p + r + 1, cmpY)->y;
Div[mid] = (maxX - minX >= maxY - minY);
nth_element(p + l, p + mid, p + r + 1, Div[mid] ? cmpX : cmpY);
build(l, mid - 1);
build(mid+1, r);
}
void find(int l, int r, Point a) //查找最近点的平方距离
{
if (l > r) return;
int mid = MID(l, r);
LL dist = dist2(a, p[mid]);
if (dist > 0) //如果有重点不能这么判断
res = min(res, dist);
LL d = Div[mid] ? (a.x - p[mid].x) : (a.y - p[mid].y);
int l1, l2, r1, r2;
l1 = l , l2 = mid + 1;
r1 = mid - 1, r2 = r;
if (d > 0)
swap(l1, l2), swap(r1, r2);
find(l1, r1, a);
if (d * d
HDOJ 4347 The Closest M Points (Q近邻)
与上题不同的是,一是k维(这个好处理~),二是求最近的m个点而不单是最近点了。这个也好处理~递归查找时处理的时候采取如下策略:如果当前找到的点小于k个,那么两个区间都要处理。。否则根据当前找到的第k个点决定是否去另外一个区间,如果目标点到分界线的距离大于等于已经找到的第k远的点,那么就不用查找另一个分界了。。。更新答案可以用一个大小为k的堆去维护(一个最大堆,一旦超过k个点就把最大的扔掉)。。。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ( (x + y)>>1 )
using namespace std;
typedef long long LL;
//KD-Tree模板
const int N=50005;
struct Point
{
int x[5];
LL dis;
Point()
{
for (int i = 0; i x[i];
maxx[i] = max_element(p + l, p + r + 1, cmpX)->x[i];
ms[maxx[i] - minx[i]] = i;
}
map ::iterator pm = ms.end();
pm--;
return pm->second;
}
void build(int l, int r) //记得先把p备份一下。
{
if (l > r) return;
int mid = MID(l,r);
Div[mid] = getDiv(l,r);
ddiv = Div[mid];
nth_element(p + l, p + mid, p + r + 1, cmpX);
build(l, mid - 1);
build(mid + 1, r);
}
void findk(int l, int r, Point a) //k(m)近邻,查找k近点的平方距离
{
if (l > r) return;
int mid = MID(l,r);
LL dist = dist2(a, p[mid], k);
if (dist >= 0)
{
p[mid].dis = dist;
res.push(p[mid]);
while ((int)res.size() > m)
res.pop();
}
LL d = a.x[Div[mid]] - p[mid].x[Div[mid]];
int l1, l2, r1, r2;
l1 = l , l2 = mid + 1;
r1 = mid - 1, r2 = r;
if (d > 0)
swap(l1, l2), swap(r1, r2);
findk(l1, r1, a);
if ((int)res.size() = 0; i--)
{
for (int j = 0; j
来源:https://www.cnblogs.com/AbandonZHANG/archive/2012/09/21/4113953.html