题意
有n个旅馆,坐标为(x,y),对应的住宿费用为c。
有m个人,处于坐标(x,y),有c元。
问对于每个人,给出在能够付出住宿费用的前提下,离他最近的旅馆的信息(欧几里得距离)。
分析
K近邻算法
考虑用KD-Tree加以解决。
不会KD-Tree的请点——KD树
代码
#include<bits/stdc++.h>
using namespace std;
const long long inf = 1ll << 60;
const int dimensions = 2; //最大维度
const int N = 200000 + 10; //最大坐标点数
int n,idx; //n—坐标点数,idx划分值(必须存在)
struct Node{
long long elemt[dimensions];
int c,id;
}src[N],ans;
long long mindist;
bool operator<(Node a,Node b){
return a.elemt[idx] < b.elemt[idx];
}
long long sqrt2(long long x){
return x*x;
}
class kdTree{
private:
bool flag[N<<2];
Node node[N<<2];
public:
void build(int l,int r,int rt,int dep);
void query(Node smp,int rt,int dep);
}kd;
void kdTree::build(int l,int r,int rt,int dep){
if(l > r) return;
flag[rt] = 1;
flag[rt<<1] = flag[rt<<1 | 1] = 0;
idx = dep % dimensions;
int mid = (l+r)>>1;
nth_element(src+l,src+mid,src+r+1);
node[rt] = src[mid];
build(l,mid-1,rt<<1,dep+1);
build(mid+1,r,rt<<1|1,dep+1);
}
void kdTree::query(Node smp,int rt,int dep){
long long dist = 0;
for(int i=0;i<dimensions;i++)
dist += sqrt2(smp.elemt[i] - node[rt].elemt[i]);
int dia = dep % dimensions;
int left = rt<<1, right = rt<<1 | 1;
if(smp.elemt[dia] >= node[rt].elemt[dia])
swap(left,right);
if(flag[left]) query(smp,left,dep+1);
if(node[rt].c <= smp.c){
if(dist == mindist && node[rt].id < ans.id) ans = node[rt];
else if(dist < mindist) ans = node[rt], mindist = dist;
}
if(flag[right] && sqrt2(node[rt].elemt[dia] - smp.elemt[dia]) <= mindist)
query(smp,right,dep+1);
}
int main(){
int T,m;
scanf("%d",&T);
while(T-- && scanf("%d %d",&n,&m)!=EOF){
for(int i=0;i<n;i++)
scanf("%I64d %I64d %d",&src[i].elemt[0],&src[i].elemt[1],&src[i].c), src[i].id = i;
kd.build(0,n-1,1,0);
ans = src[0];
Node smp;
for(int i=0;i<m;i++){
scanf("%I64d %I64d %d",&smp.elemt[0],&smp.elemt[1],&smp.c);
mindist = inf;
kd.query(smp,1,0);
printf("%I64d %I64d %d\n",ans.elemt[0],ans.elemt[1],ans.c);
}
}
}