欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
参考资料
https://blog.csdn.net/qq_34107425/article/details/106321837 查询最近点
https://blog.csdn.net/qq_38019633/article/details/89555909 查询最近k个点
#include#include #include #include #include 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 scanf("%lf%lf",&points[i].first, &points[i].second); points[i].i=i; } int root = buildTree(0, n-1); for(int i=0;i double m = dis(points[i], points[1]); if(i)m = dis(points[i], points[0]); query(&nodePool[root], points[i], m); printf("%.2lfn", m/2); } } } int main() { solve(); return 0; }
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。



