欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
参考资料
https://blog.csdn.net/qq_34107425/article/details/106321837 查询最近点
https://blog.csdn.net/qq_38019633/article/details/89555909 查询最近k个点
代码实现
#include <iostream>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
enum dimension {
X=0, Y=1
};
class P {
public:
double first, second;
int i;
};
bool cmp0(const P a,const P b) {
return a.first< b.first;
}
bool cmp1(const P a, const P b) {
return a.second< b.second;
}
class KDNode {
public:
dimension d; // 按哪一维划分
P center; // 分割点
int i;
KDNode *left, *right;
};
const int N =200100;
KDNode nodePool[N];
int used = 0;
int getNode() {
nodePool[used].left=NULL;
nodePool[used].right=NULL;
used++;
return used-1;
}
P points[N];
// 获取方差
double getVariance(int l, int r, dimension D) {
double average=0;
for(int i=l;i<=r;++i) {
if(D==X) average+=points[i].first;
if(D==Y) average+=points[i].second;
}
average /= r-l+1;
double variance=0;
for(int i=l;i<=r;++i) {
if(D==X) variance+=pow(points[i].first-average, 2);
if(D==Y) variance+=pow(points[i].second-average, 2);
}
variance /= r-l+1;
return variance;
}
int buildTree(int l, int r) {
if(l>r)return -1;
int root = getNode();
if (l == r) {
nodePool[root].d=X;
nodePool[root].center = points[l];
nodePool[root].i = points[l].i;
return root;
}
// 计算方差
double varianceX = getVariance(l, r, X);
double varianceY = getVariance(l, r, Y);
if(varianceY>varianceX) {
sort(points+l, points+r+1, cmp1);
nodePool[root].d=Y;
}
else {
sort(points+l, points+r+1, cmp0);
nodePool[root].d=X;
}
int mid = (l+r)>>1;
nodePool[root].center = points[mid];
nodePool[root].i = points[mid].i;
int left = buildTree(l, mid-1);
if(left>=0)nodePool[root].left = &nodePool[left];
int right = buildTree(mid+1, r);
if(right>=0)nodePool[root].right = &nodePool[right];
return root;
}
bool isToLeft(KDNode * root, P target) {
if(root->d == X) return target.first < root->center.first;
return target.second < root->center.second;
}
bool isCross(KDNode * root, P target, double r) {
if(root->d == X) {
return fabs(target.first - root->center.first)>r;
}
return fabs(target.second < root->center.second)>r;
}
double dis( P a, P b) {
a.first-=b.first;
a.second -= b.second;
return sqrt(a.first*a.first + a.second*a.second);
}
void query(KDNode * root, P target, double &ans) {
if(root==NULL)return;
bool toLeft;
// 查询某个分支
if(root->left && isToLeft(root, target)) {
query(root->left, target, ans);
toLeft=true;
} else if(root->right && !isToLeft(root, target)) {
query(root->right, target, ans);
toLeft=false;
}
// 是否查询另一边
if(isCross(root, target, ans)) {
if(toLeft && root->right) query(root->right, target, ans);
if(!toLeft && root->left) query(root->left, target, ans);
}
// 计算自身
if(root->i != target.i)ans = min(ans, dis(root->center, target));
}
void solve() {
int n=0;
while(scanf("%d", &n)!=EOF &&n) {
used = 0;
for(int i=0;i<n;i++) {
scanf("%lf%lf",&points[i].first, &points[i].second);
points[i].i=i;
}
int root = buildTree(0, n-1);
for(int i=0;i<n;i++) {
double m = dis(points[i], points[1]);
if(i)m = dis(points[i], points[0]);
query(&nodePool[root], points[i], m);
printf("%.2lf\n", m/2);
}
}
}
int main() {
solve();
return 0;
}
/*
*/
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。