hdu 4347 The Closest M Points (kd树)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4347 The Closest M Points (kd树)相关的知识,希望对你有一定的参考价值。
题意:
求k维空间中离所给点最近的m个点,并按顺序输出 。
解法:
kd树模板题 。
不懂kd树的可以先看看这个 。
不多说,上代码 。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #include <queue> 7 #include <set> 8 #include <vector> 9 #include <map> 10 #define ll long long 11 12 using namespace std; 13 14 const int N=50007; 15 const int K=6; 16 17 int n,m; 18 19 struct point{ 20 int a[K]; 21 int div; // 按哪个维度划分 22 bool lef; // 是否是叶子节点 23 ll dis; // 离询问点的距离。注意这个在读入建树时不会用到,在进入队列时才用到 24 void print(){ 25 printf("%d",a[0]); 26 for (int i=1;i<m;i++) 27 printf(" %d",a[i]); 28 puts(""); 29 } 30 bool operator < (const point &t) const{ 31 return dis<t.dis; 32 } 33 point(){} 34 point(point &t,ll d){ 35 for (int i=0;i<m;i++) a[i]=t.a[i]; 36 dis=d; 37 } 38 }p[N],tar; 39 40 int cmp_NO; 41 inline bool cmp(point x,point y){ 42 return x.a[cmp_NO]<y.a[cmp_NO]; 43 } 44 45 inline ll dis(point x,point y){ 46 ll ret=0; 47 for (int i=0;i<m;i++) 48 ret+=(x.a[i]-y.a[i])*(x.a[i]-y.a[i]); 49 return ret; 50 } 51 52 inline void bulid_kdt(int L,int R,int d){ 53 if (L>R) return; 54 int mid=(L+R)>>1; 55 cmp_NO=d; 56 nth_element(p+L,p+mid,p+R+1,cmp); 57 p[mid].div=d; 58 if (L==R){ 59 p[L].lef=true; 60 return; 61 } 62 bulid_kdt(L,mid-1,(d+1)%m); 63 bulid_kdt(mid+1,R,(d+1)%m); 64 } 65 66 priority_queue<point> que; 67 int num,nownum; 68 ll ans; 69 70 inline void find_kd(int L,int R){ 71 if (L>R) return; 72 73 int mid=(L+R)>>1; 74 ll d=dis(p[mid],tar); 75 if (p[mid].lef){ 76 if (nownum<num){ 77 nownum++; 78 que.push(point(p[mid],d)); 79 ans=max(ans,d); 80 } 81 else if (ans>d){ 82 que.pop(); 83 que.push(point(p[mid],d)); 84 ans=que.top().dis; 85 } 86 return; 87 } 88 89 int t=tar.a[p[mid].div]-p[mid].a[p[mid].div]; 90 if (t>0){ 91 find_kd(mid+1,R); 92 if (nownum<num){ 93 nownum++; 94 que.push(point(p[mid],d)); 95 ans=max(ans,d); 96 find_kd(L,mid-1); 97 } 98 else { 99 if (ans>d){ 100 que.pop(); 101 que.push(point(p[mid],d)); 102 ans=que.top().dis; 103 } 104 if (ans>t*t) 105 find_kd(L,mid-1); 106 } 107 } 108 else { 109 find_kd(L,mid-1); 110 if (nownum<num){ 111 nownum++; 112 que.push(point(p[mid],d)); 113 ans=max(ans,d); 114 find_kd(mid+1,R); 115 } 116 else{ 117 if (ans>d){ 118 que.pop(); 119 que.push(point(p[mid],d)); 120 ans=que.top().dis; 121 } 122 if (ans>t*t) 123 find_kd(mid+1,R); 124 } 125 } 126 } 127 128 inline void put(){ 129 if (que.empty()) return; 130 point pp=que.top(); 131 que.pop(); 132 put(); 133 pp.print(); 134 } 135 136 int main(){ 137 while (~scanf("%d%d",&n,&m)){ 138 for (int i=0;i<n;i++){ 139 for (int j=0;j<m;j++) 140 scanf("%d",&p[i].a[j]); 141 p[i].lef=false; 142 } 143 144 bulid_kdt(0,n-1,0); // 这一步相当于将原数组重新排了个序,先访问到的点放在中间 145 146 int q; 147 scanf("%d",&q); 148 while (q--){ 149 for (int i=0;i<m;i++) 150 scanf("%d",&tar.a[i]); 151 while (!que.empty()) que.pop(); 152 scanf("%d",&num); 153 nownum=0; 154 ans=-1; 155 find_kd(0,n-1); 156 printf("the closest %d points are:\n",num); 157 put(); 158 } 159 } 160 return 0; 161 }
以上是关于hdu 4347 The Closest M Points (kd树)的主要内容,如果未能解决你的问题,请参考以下文章
数据结构(KD树):HDU 4347 The Closest M Points
hdu4347The Closest M Points KD树模板
The Closest M Points bzoj 3053