HDU 1007(套圈 最近点对距离)

题意是求出所给各点中最近点对的距离的一半(背景忽略)。

用分治的思想,先根据各点的横坐标进行排序,以中间的点为界,分别求出左边点集的最小距离和右边点集的最小距离,然后开始合并,分别求左右点集中各点与中间点的距离,从这些距离与点集中的最小距离比较,求得最小距离,此处可按纵坐标排序,将纵坐标距离已经大于之前最小距离的部分都剪枝。

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n,a[100009];
 4 struct point
 5 {
 6     double x,y;
 7 }p[100009];
 8 bool cmpx(point a,point b)
 9 {
10     return a.x < b.x;
11 }
12 bool cmpy(int a,int b)
13 {
14     return p[a].y < p[b].y;
15 }
16 double dis(point a,point b)
17 {
18     return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
19 }
20 double min(double a,double b,double c)
21 {
22     if(a>b) return b>c?c:b;
23     return a>c?c:a;
24 }
25 double fin(int from,int to)
26 {
27     if(from+1 == to ) return dis(p[from],p[to]);
28     if(from+2 == to ) return min(dis(p[from],p[from+1]),dis(p[from],p[to]),dis(p[from+1],p[to]));
29     int mid = (from+to)>>1;
30     double ans = min(fin(from,mid),fin(mid+1,to));
31     int cnt = 0;
32     for(int i = from; i <= to; i++)
33         if(abs(p[i].x-p[mid].x) <= ans) a[cnt++] = i;
34     sort(a,a+cnt,cmpy);
35     for(int i = 0; i < cnt; i++)
36         for(int j = i+1; j < cnt; j++)
37         {
38             if(p[a[j]].y-p[a[i]].y >= ans) break;
39             ans = min(ans,dis(p[a[i]],p[a[j]]));
40         }
41     return ans;
42 }
43 int main()
44 {
45     while(scanf("%d",&n)&&n)
46     {
47         for(int i = 0; i < n; i++)
48             scanf("%lf %lf",&p[i].x,&p[i].y);
49         sort(p,p+n,cmpx);
50         printf("%.2lf
",fin(0,n-1)/2);
51     }
52     return 0;
53 }
View Code

但是呢,开始时本人并不是这么写的,而是求了所有点中最小的横坐标和纵坐标,然后以此为参照点,分别求其他各点到参照点的距离,以距离排序,再求出相邻两点距离的最小值。这么写是上面写法的用时一半左右,尽管 AC 了,但是这么写是不对的......

如图所示,图中的点 1 和点 2 距离比点 1 和点 3 的距离更近,但是第二种方法则是用点 1 和点 3距离与点 3 和点 2 距离中求较小值。(题目的测试数据中可能没有这样的数据吧......)

第二种方法的代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 struct point
 5 {
 6     double x,y,dis;
 7 }st,p[100009];
 8 bool cmp(point a,point b)
 9 {
10     if(a.dis!=b.dis) return a.dis < b.dis;
11     return a.x<b.x;
12 }
13 double dist(point a,point b)
14 {
15     return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
16 }
17 int main()
18 {
19     double sml;
20     while(scanf("%d",&n)&&n)
21     {
22         st.x = st.y = 1000000.0;
23         sml = 1000000.0;
24         for(int i = 0; i < n; i++)
25         {
26             scanf("%lf %lf",&p[i].x,&p[i].y);
27             if(p[i].x < st.x) st.x = p[i].x;
28             if(p[i].y < st.y) st.y = p[i].y;
29         }
30         for(int i = 0; i < n; i++)
31             p[i].dis = dist(p[i],st);
32         sort(p,p+n,cmp);
33         for(int i = 1; i < n; i++)
34             if(dist(p[i],p[i-1])<sml) sml = dist(p[i],p[i-1]);
35         printf("%.2lf
",sml/2);
36     }
37     return 0;
38 }
View Code
日后若能有更好的想法,再来完善。 希望看到的大神不吝赐教 orz
原文地址:https://www.cnblogs.com/Taskr212/p/9513210.html