zoukankan      html  css  js  c++  java
  • kd树解平面最近点对

    早上起来头有点疼,突然就想到能不能用kd树解平面最近点对问题,就找了道题试了一下,结果可以,虽然效率不高,但还是AC了~

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007

    题目要求平面上最近点对间距离的一半。

    思路如下:先建立一棵树,所有点插入树中,之后为每个点查询其最近点,枚举找到最小值。注意查询的时候不要让点自己跟自己比。个人感觉,这种写法也可以达到O(nlogn)的复杂度。建树分区间的时候,按x,y中跨度大的一个来分,应该就接近O(nlogn)了,不过我太懒了,那种方法之后再试,现在先x,y轮流着来了。

    kd树代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 #include <cstdio>
     6 #include <cmath>
     7 #define MAX (101000)
     8 #define pow(x) ((x)*(x))
     9 
    10 using namespace std;
    11 
    12 int n, idx;
    13 
    14 struct Point{
    15     double x[2];
    16     bool operator < (const Point &u) const{
    17         return x[idx] < u.x[idx];
    18     }
    19 }po[MAX];
    20 
    21 struct Tree {
    22     Point p[MAX<<2];
    23     int son[MAX<<2];
    24     bool f[MAX<<2];
    25     int ps[MAX<<2];
    26     void build ( int l , int r , int u = 1, int dep = 0)
    27     {
    28         if(l > r) return;
    29         son[u] = r-l;
    30         son[u<<1] = son[u<<1|1] = -1;
    31         idx = dep%2;
    32         int mid = (l+r)>>1;
    33         nth_element(po+l, po+mid, po+r+1);
    34         p[u] = po[mid], ps[u] = mid;
    35         build ( l , mid-1 , u<<1 , dep+1 );
    36         build ( mid+1 , r , u<<1|1 , dep+1 );
    37     }
    38 
    39     double query(Point a, int id, int u = 1, int dep = 0){
    40         if(son[u] == -1) return 1000000000.0;
    41 
    42         double dis = pow(p[u].x[0]-a.x[0]) + pow(p[u].x[1]-a.x[1]);
    43         if(ps[u] == id) dis = 1000000000.0;
    44         int dim = dep%2, fg = 0;
    45         int x = u<<1, y = u<<1|1;
    46         if(a.x[dim] >= p[u].x[dim]) swap(x, y);
    47         double tm1 = 1000000000.0, tm2 = 1000000000.0;
    48         if(~son[x])tm1 = query(a, id, x, dep+1);
    49         if(pow(a.x[dim] - p[u].x[dim]) < tm1) fg = 1;
    50         if(~son[y] && fg) tm2 = query(a, id, y, dep+1);
    51         if(dis > tm1) dis = tm1;
    52         if(dis > tm2) dis = tm2;
    53         return dis;
    54     }
    55 }kd;
    56 
    57 
    58 int main(){
    59     while(~scanf("%d", &n), n){
    60         for(int i = 0; i < n; i++)
    61                 scanf("%lf %lf", &po[i].x[0], &po[i].x[1]);
    62         memset(kd.f, 0, sizeof(kd.f));
    63         memset(kd.ps, -1, sizeof(kd.ps));
    64         kd.build(0, n-1);
    65         double ans = 1000000000.0;
    66         for(int i = 0; i < n; i++){
    67             double tm = kd.query(po[i], i);
    68             if(tm < ans) ans = tm;
    69         }
    70         printf("%.2lf
    ", sqrt(ans)/2);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    小白扫盲之-计算机为何需要内存
    Centos 安装Pycharm 并移动到桌面。
    Docker守护进程
    插入排序
    快速排序
    归并排序
    __metaclass__方法
    Python面向对象(2)类空间问题以及类之间的关系
    Python面向对象(1)_初步认识
    python语法基础(8)_包
  • 原文地址:https://www.cnblogs.com/beisong/p/4427654.html
Copyright © 2011-2022 走看看