题意:求K维空间中给定一个点最邻近的M个点。
思路:KD树模板题,
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PI;
typedef pair< PI, int> PII;
#define pb push_back
#define Key_value ch[ch[root][1]][0]
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define MS(x,y) memset(x,y,sizeof(x))
const double eps=1e-6;
const double pi=acos(-1.0);
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int M = 1000100;
const int MAXN =50010;
const int DIM=10;
inline double sqr(double x)
{
return x*x;
}
namespace KDTree
{
int k;
struct Point
{
int x[DIM];
double distance(const Point &b)const
{
double ret=0;
for(int i=0; i<k; ++i)
ret+=sqr(x[i]-b.x[i]);
return ret;
}
};
struct qnode
{
Point p;
double dis;
qnode(Point _p,double _dis)
{
p=_p;
dis=_dis;
}
bool operator <(const qnode &b)const
{
return dis<b.dis;
}
};
priority_queue<qnode>q;
struct cmpx
{
int div;
cmpx(const int &_div)
{
div=_div;
}
bool operator ()(const Point &a,const Point &b)
{
for(int i=0; i<k; ++i)
if(a.x[(div+i)%k]!=b.x[(div+i)%k])
return a.x[(div+i)%k]<b.x[(div+i)%k];
return true;
}
};
bool cmp(const Point &a,const Point &b,int div)
{
cmpx cp=cmpx(div);
return cp(a,b);
}
struct Node
{
Point e;
Node *lc,*rc;
int div;
} pool[MAXN],*tail,*root;
void init()
{
tail=pool;
}
Node* build(Point *a,int l,int r,int div)
{
if(l>=r) return NULL;
Node *p=tail++;
p->div=div;
int mid=(l+r)/2;
nth_element(a+l,a+mid,a+r,cmpx(div));
p->e=a[mid];
p->lc=build(a,l,mid,(div+1)%k);
p->rc=build(a,mid+1,r,(div+1)%k);
return p;
}
void search(Point p,Node *x,int div,int m)
{
if(!x) return;
if(cmp(p,x->e,div))
{
search(p,x->lc,(div+1)%k,m);
if(q.size()<m)
{
q.push(qnode(x->e,p.distance(x->e)));
search(p,x->rc,(div+1)%k,m);
}
else
{
if(p.distance(x->e) < q.top().dis)
{
q.pop();
q.push(qnode(x->e,p.distance(x->e)));
}
if(sqr(x->e.x[div]-p.x[div])<q.top().dis)
search(p,x->rc,(div+1)%k,m);
}
}
else
{
search(p,x->rc,(div+1)%k,m);
if(q.size()<m)
{
q.push(qnode(x->e,p.distance(x->e)));
search(p,x->lc,(div+1)%k,m);
}
else
{
if(p.distance(x->e) < q.top().dis)
{
q.pop();
q.push(qnode(x->e,p.distance(x->e)));
}
if(sqr(x->e.x[div]-p.x[div])<q.top().dis)
search(p,x->lc,(div+1)%k,m);
}
}
}
void search(Point p,int m)
{
while(!q.empty())q.pop();
search(p,root,0,m);
}
};
KDTree::Point p[MAXN];
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
KDTree::k=k;
for(int i=0; i<n; ++i)
{
for(int j=0; j<k; ++j)
{
scanf("%d",&p[i].x[j]);
}
}
KDTree::init();
KDTree::root=KDTree::build(p,0,n,0);
KDTree::Point tmp;
int Q;
scanf("%d",&Q);
while(Q--)
{
for(int i=0; i<k; ++i)
scanf("%d",&tmp.x[i]);
int m;
scanf("%d",&m);
KDTree::search(tmp,m);
int cnt=0;
while(!KDTree::q.empty())
{
p[cnt++]=KDTree::q.top().p;
KDTree::q.pop();
}
printf("the closest %d points are:\n",m);
for(int i=0; i<cnt; ++i)
{
for(int j=0; j<k; ++j)
printf("%d%c",p[cnt-1-i].x[j],j==k-1?'\n':' ');
}
}
}
return 0;
}
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/1315 (转载时请注明本文出处及文章链接)


发表评论
快来吐槽一下吧!