ALLap

导航

 
题意:求平面上n个点中最短的两个点的距离

思想:分治法

1:暴力枚举法一般都超时啦,复杂度为O(n^2)
2:分治法
将n个点划分为左右两部分,为使两边尽量均匀,一般以所谓点的横坐标的平均值为界。则最段点对要么在左边点中,要么在右边点中,要么横跨分界线。取左右点集合中最小值,再以它为范围,以分界线为中轴划出一部分区域,则横跨分界线的情况只可能在这部分区域中。最后取三者最小值即可。
对于左右两部分,则是简单的子问题,直接递归调用即可,而对于中间部分,由于区域被划小了,直接枚举一个个比较。
代码:
 1 #include <iostream>
 2 #include <cmath>
 3 #include <algorithm>
 4 using namespace std;
 5 #define MAXN 10000
 6 const int INF = 9999999;
 7 
 8 struct node
 9 {
10     double x, y;
11 }p[MAXN], ym[MAXN];
12 
13 int n;
14 
15 int cmpx(const node a, const node b)
16 {
17     return a.x < b.x;
18 }
19 
20 int cmpy(const node a, const node b)
21 {
22     return a.y < b.y;
23 }
24 
25 double dist(node a, node b)
26 {
27     return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
28 }
29 
30 double getmind(node *p, int l, int r)
31 {
32     if(l == r) return INF; //只有一个点
33     if(l+1 == r) return dist(p[l], p[r]);//只有两个点 
34     int mid = (l+r)/2;
35     double ans = min(getmind(p, l,mid), getmind(p, mid+1, r));
36     int yn = 0;
37     for(int i = l; i <= r ; i++)
38     {
39         if(fabs(p[i].x - p[mid].x) <= ans)//满足这样的才有比较的意义
40         {
41             ym[yn++] = p[i];
42         }
43     }
44     sort(ym, ym+yn, cmpy); //预排序 
45     for(int i = 0; i < yn; i++)
46     {
47         for(int j = i+1; j < yn; j++)
48         {
49             if((ym[j].y - ym[i].y) >= ans) break; //if(|y1-y2| >= ans) break;
50             ans = min(ans, dist(ym[i], ym[j]));
51         }
52     }
53     return ans;
54 }
55 
56 int main()
57 {
58     int T;
59     scanf("%d", &T);
60     while(T--)
61     {
62         scanf("%d", &n);
63         for(int i = 0; i < n; i++)
64         {
65             scanf("%lf%lf", &p[i].x, &p[i].y);
66         }
67         sort(p, p+n, cmpx);
68         double ans = getmind(p, 0,n-1);
69             printf("%.3f\n", ans);
70     }
71     return 0;
72 }
变形:最短点对分别属于两个点集
接近方法:稍稍改变,标记两个点集,若两点属于同一个点集,则将距离设为最大值
代码:
 1 #include <iostream>
 2 #include <cmath>
 3 #include <algorithm>
 4 using namespace std;
 5 #define MAXN 100010
 6 const int INF =999999;
 7 
 8 struct node
 9 {
10     double x, y;
11     int f;//用来标记两个点集
12 }p[MAXN], ym[MAXN];
13 
14 int n;
15 
16 int cmpx(const node a, const node b)
17 {
18     return a.x < b.x;
19 }
20 
21 int cmpy(const node a, const node b)
22 {
23     return a.y < b.y;
24 }
25 
26 double dist(node a, node b)
27 {
28     if(a.f * b.f > 0) return INF;
29     return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
30 }
31 
32 double getmind(node *p, int l, int r)
33 {
34     if(l == r) return INF; //只有一个点
35     if(l+1 == r) return dist(p[l], p[r]);    //只有两个点 
36     int mid = (l+r)/2;
37     double ans = min(getmind(p, l,mid), getmind(p, mid+1, r));
38     int yn = 0;
39     for(int i = l; i <= r ; i++)   //divide
40     {
41         if(fabs(p[i].x - p[mid].x) <= ans)
42         {
43             ym[yn++] = p[i];
44         }
45     }
46     sort(ym, ym+yn, cmpy); //预排序 
47     for(int i = 0; i < yn; i++)
48     {
49         for(int j = i+1; j < yn; j++)
50         {
51             if(ym[j].y - ym[i].y >= ans) break; //if(|y1-y2| >= ans) break;
52             ans = min(ans, dist(ym[i], ym[j]));
53         }
54     }
55     return ans;
56 }
57 
58 
59 int main()
60 {
61     int T;
62     scanf("%d", &T);
63     while(T--)
64     {
65         scanf("%d", &n);
66         for(int i = 0; i < n; i++)
67         {
68             scanf("%lf%lf", &p[i].x, &p[i].y);
69             p[i].f = 1;
70         }
71         for(int i = n; i < 2*n ; i++)
72         {
73             scanf("%lf%lf", &p[i].x, &p[i].y);
74             p[i].f = -1;
75         }
76         sort(p, p+2*n, cmpx);
77         double ans = getmind(p, 0, 2*n-1);
78             printf("%.3f\n", ans);
79     }
80     return 0;
81 }

 

posted on 2016-12-11 22:27  ALLap  阅读(195)  评论(0)    收藏  举报