poj4091The Closest M Points(KD-tree)

kd-tree参考资料:

http://my.oschina.net/keyven/blog/221792

http://blog.csdn.net/lsjseu/article/details/12344443

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <queue>
  4 #include <cstring>
  5 using namespace std;
  6
  7 const int MAXD = 5, MAXT = 5010;
  8 int n, k, m, cur=1, curd;
  9
 10 class point{
 11 public:
 12     int a[MAXD];
 13 }pa[MAXT], tp;
 14 inline int sqr(int a){return a*a; }
 15 int dis(point &a, point &b){
 16     int res=0;
 17     for(int i=0; i<k; ++i)
 18         res += sqr(a.a[i]-b.a[i]);
 19     return res;
 20 }
 21
 22 class cmp{
 23 public:
 24     int operator()(const int &i, const int &j){
 25         return dis(tp,pa[i])<dis(tp,pa[j]);
 26     }
 27 }less_than;
 28
 29 int comp(const point &i, const point &j){// 比较curd维的大小
 30     return i.a[curd]<j.a[curd];
 31 }
 32 priority_queue<int,vector<int>,cmp > max_heap;
 33
 34 class node{
 35 public:
 36     int l,r,dim,lc,rc,idx;
 37 }kdt[MAXT*2];// 线段树,范围:[l,r]
 38 void build_kdt(int lf, int rt, int d){
 39     int m = (lf+rt)>>1;
 40     curd = d;
 41     nth_element(pa+lf, pa+m, pa+rt+1, comp);
 42     node &root = kdt[cur++];
 43     root.l = lf, root.r = rt, root.dim = d,    root.idx = m;
 44     if(lf<m){
 45         root.lc = cur;
 46         build_kdt(lf, m-1, (d+1)%k);
 47     }
 48     if(m<rt){
 49         root.rc = cur;
 50         build_kdt(m+1, rt, (d+1)%k);
 51     }
 52 }
 53 void query(int r){
 54     if(r<=0) return;
 55     node &rt = kdt[r];
 56     // 访问当前结点
 57     if(max_heap.size()<m)
 58         max_heap.push(rt.idx);
 59     else if(less_than(rt.idx, max_heap.top())){
 60         max_heap.pop();
 61         max_heap.push(rt.idx);
 62     }
 63     int fir, sec;
 64     if(tp.a[rt.dim]<pa[rt.idx].a[rt.dim])
 65         fir = rt.lc, sec = rt.rc;
 66     else fir = rt.rc, sec = rt.lc;
 67     query(fir);// 访问目标所在的结点的子树,并进行是否在另一子树的判断
 68     if(max_heap.size()<m || dis(pa[max_heap.top()], tp)>=sqr(tp.a[rt.dim]-pa[rt.idx].a[rt.dim])){
 69         query(sec);
 70     }
 71 }
 72
 73 void print(){// 从小到大输出最大堆
 74     if(!max_heap.empty()){
 75         int i = max_heap.top(); max_heap.pop();
 76         print();
 77         for(int j=0; j<k; ++j)
 78             printf("%d ", pa[i].a[j]);
 79         printf("\n");
 80     }
 81 }
 82
 83 int main(){
 84     // freopen("in.txt", "r", stdin);
 85     int t;
 86     while(scanf("%d%d", &n, &k) == 2){
 87         for(int i=0; i<n; ++i){
 88             for(int j=0; j<k; ++j)
 89                 scanf("%d", &pa[i].a[j]);
 90         }
 91         memset(kdt, 0, sizeof(kdt));
 92         cur = 1;
 93         build_kdt(0,n-1,0);
 94         scanf("%d", &t);
 95         while(t--){
 96             for(int i=0; i<k; ++i) scanf("%d", &tp.a[i]);
 97             scanf("%d", &m);
 98             printf("the closest %d points are:\n", m);
 99             while(!max_heap.empty()) max_heap.pop();
100             query(1);
101             print();
102         }
103     }
104     return 0;
105 }
时间: 2024-12-12 03:50:43

poj4091The Closest M Points(KD-tree)的相关文章

bzoj 3053 HDU 4347 : The Closest M Points kd树

bzoj 3053 HDU 4347 : The Closest M Points  kd树 题目大意:求k维空间内某点的前k近的点. 就是一般的kd树,根据实测发现,kd树的两种建树方式,即按照方差较大的维度分开(建树常数大)或者每一位轮换分割(询问常数大),后者更快也更好些,以后就果断写第二种了. #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using

hdu 4347 The Closest M Points (kd树)

hdu 4347 题意: 求k维空间中离所给点最近的m个点,并按顺序输出  . 解法: kd树模板题 . 不懂kd树的可以先看看这个 . 不多说,上代码 . 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <queue> 7 #include <s

The Closest M Points//kd树+优先队列

题目 The Closest M Points Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) Total Submission(s): 7570 Accepted Submission(s): 2378 Problem Description The course of Software Design and Development Practice is objectionab

数据结构(KD树):HDU 4347 The Closest M Points

The Closest M Points Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)Total Submission(s): 3285    Accepted Submission(s): 1201 Problem Description The course of Software Design and Development Practice is objection

【hdu4347】The Closest M Points 【KD树模板】

题意 一个k维空间,给出n个点的坐标,给出t个询问,每个询问给出一个点的坐标和一个m.对于每个询问找出跟这个点最接近的m个点 分析 kd树的模板题. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 7 using namespace std; 8 typedef long long

【BZOJ】【3053】The Closest M Points

KD-Tree 题目大意:K维空间内,与给定点欧几里得距离最近的 m 个点. KD树啊……还能怎样啊……然而扩展到k维其实并没多么复杂?除了我已经脑补不出建树过程……不过代码好像变化不大>_> 然而我WA了...为什么呢...我也不知道…… 一开始我的Push_up是这么写的: inline void Push_up(int o){ rep(i,k){ if (L) t[o].mn[i]=min(t[o].mn[i],t[L].mn[i]),t[o].mx[i]=max(t[o].mx[i],

【BZOJ 3053】 The Closest M Points

3053: The Closest M Points Time Limit: 10 Sec Memory Limit: 128 MB Submit: 376 Solved: 146 [Submit][Status][Discuss] Description The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many

k-d tree学习总结

本文转载自http://blog.csdn.net/zhjchengfeng5/article/details/7855241# 首先来一个问题: 给定平面上一个点集 E ,还有一个定点 V ,怎么在一群点中找出一个点 U,使得 V 与 U 的距离最近(欧几里得距离)? 当然,我们能够想到一种做法:枚举 E 中所有的点,找出它们中距离V 最近的点 U. 但是,假设现在有两个点集 E1 与 E2 ,对于 E2 中每一个点 Vi ,找出一个在E1 中的一个点 Ui,使得 Vi 到 Ui 的距离最短,

【BZOJ】3053: The Closest M Points(kdtree)

http://www.lydsy.com/JudgeOnline/problem.php?id=3053 本来是1a的QAQ.... 没看到有多组数据啊.....斯巴达!!!!!!!!!!!!!!!!! 本题裸的kdtree,比上一题还要简单...................................... 对于当前点,判断进入左或右子树,然后看答案是否能过分割线..如果能,进入右或左子树.........并且如果答案个数小于k,也要进入.. 然后就浪吧........... #inc