首页 > 代码库 > hdu 4347 The Closest M Points (kd树)
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 <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树)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。