码迷,mamicode.com
首页 > 其他好文 > 详细

kd树解平面最近点对

时间:2015-04-15 10:51:24      阅读:367      评论:0      收藏:0      [点我收藏+]

标签:

早上起来头有点疼,突然就想到能不能用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\n", sqrt(ans)/2);
71     }
72     return 0;
73 }

 

kd树解平面最近点对

标签:

原文地址:http://www.cnblogs.com/beisong/p/4427654.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!