poj3608Bridge Across Islands(凸包间最小距离)

链接

以下所有文章均转载( http://blog.csdn.net/acmaker/article/details/3176910) 转载请注明出处!

考虑如下的算法, 算法的输入是两个分别有 m 和 n 个顺时针给定顶点的凸多边形 P 和 Q。

  1. 计算 P 上 y 坐标值最小的顶点(称为 yminP ) 和 Q 上 y 坐标值最大的顶点(称为 ymaxQ)。
  2. 为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧。 此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和 ymaxQ 成为了多边形间的一个对踵点对。
  3. 计算距离(yminP,ymaxQ) 并且将其维护为当前最小值。
  4. 顺时针同时旋转平行线直到其中一个与其所在的多边形的边重合。
  5. 如果只有一条线与边重合, 那么只需要计算“顶点-边”对踵点对和“顶点-顶点”对踵点对距离。 都将他们与当前最小值比较, 如果小于当前最小值则进行替换更新。 如果两条切线都与边重合, 那么情况就更加复杂了。 如果边“交叠”, 也就是可以构造一条与两条边都相交的公垂线(但不是在顶点处相交), 那么就计算“边-边”距离。 否则计算三个新的“顶点-顶点”对踵点对距离。 所有的这些距离都与当前最小值进行比较, 若小于当前最小值则更新替换。
  6. 重复执行步骤4和步骤5, 直到新的点对为(yminP,ymaxQ)。
  7. 输出最大距离。

以上是转载。。以下是原创。。

上面是按顺时针存的凸包也是按顺时针旋转的平行线,网上很多是逆时针的凸包却写着顺时针的做法,但代码依旧A了,,不是很理解。。

逆时针 改反一点 依旧A。。。

感觉自己 的是对的吧。。。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 using namespace std;
 11 #define N 10010
 12 #define LL long long
 13 #define INF 0xfffffff
 14 const double eps = 1e-9;
 15 const double pi = acos(-1.0);
 16 const double inf = ~0u>>2;
 17 struct Point
 18 {
 19     double x,y;
 20     Point(double x=0,double y=0):x(x),y(y) {} //构造函数 方便代码编写
 21 }p[N],q[N];
 22 typedef Point pointt;
 23 pointt operator + (Point a,Point b)
 24 {
 25     return Point(a.x+b.x,a.y+b.y);
 26 }
 27 pointt operator - (Point a,Point b)
 28 {
 29     return Point(a.x-b.x,a.y-b.y);
 30 }
 31 int dcmp(double x)
 32 {
 33     if(fabs(x)<eps) return 0;
 34     else return x<0?-1:1;
 35 }
 36 bool operator == (const Point &a,const Point &b)
 37 {
 38     return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
 39 }
 40 double dot(Point a,Point b)
 41 {
 42     return a.x*b.x+a.y*b.y;
 43 }
 44 double  dis(Point a)
 45 {
 46     return sqrt(dot(a,a));
 47 }
 48 double cross(Point a,Point b)
 49 {
 50     return a.x*b.y-a.y*b.x;
 51 }
 52 void anticlock(Point p[],int n)
 53 {
 54     for(int i = 0 ; i < n-2 ; i++)
 55     {
 56         double k = cross(p[i+1]-p[0],p[i+2]-p[0]);
 57         if(dcmp(k)>0) return ;
 58         else if(dcmp(k)<0)
 59         {
 60             reverse(p,p+n);
 61             return ;
 62         }
 63     }
 64 }
 65 double distoline(Point a,Point b,Point c)
 66 {
 67     if(dcmp(dis(a-b))==0) return dis(a-c);
 68     if(dcmp(dot(a-b,a-c))<0) return dis(a-c);
 69     if(dcmp(dot(b-a,b-c))<0) return dis(b-c);
 70     return fabs(cross(a-b,a-c))/dis(a-b);
 71 }
 72 double dist(Point a,Point b,Point c,Point d)
 73 {
 74     double ans = distoline(a,b,c);
 75     ans = min(ans,distoline(a,b,d));
 76     ans = min(ans,distoline(c,d,a));
 77     ans = min(ans,distoline(c,d,b));
 78     return ans;
 79 }
 80 double mul(Point a,Point b,Point c)
 81 {
 82     return cross(b-a,c-a);
 83 }
 84 double  solve(Point p[],int n,Point q[],int m)
 85 {
 86     int i;
 87     int miny = 0,maxy = 0;
 88     for(i = 0;i < n; i++)
 89     {
 90         if(p[i].y<p[miny].y)
 91         miny = i;
 92     }
 93     for(i =0 ; i< m ; i++)
 94     if(q[i].y>q[maxy].y) maxy = i;
 95     double ans = dis(p[miny]-q[maxy]);
 96     for(i = 0 ;i < n; i++)
 97     {
 98         double tmp;
 99         while(tmp = mul(p[miny],p[miny+1],q[maxy+1])-mul(p[miny],p[miny+1],q[maxy])>eps)
100         maxy = (maxy+1)%m;
101         if(dcmp(tmp)>0) ans = min(ans,distoline(p[miny],p[miny+1],q[maxy]));//这里如果写成<0 画图可以看出是顺时针的做法 就算不加这句直接算下面的也能A。。
102         else
103         ans = min(ans,dist(p[miny],p[miny+1],q[maxy],q[maxy+1]));//边-边
104         miny = (miny+1)%n;
105     }
106     return ans;
107 }
108 int main()
109 {
110     int i,n,m;
111     while(scanf("%d%d",&n,&m)&&n&&m)
112     {
113         for(i = 0 ; i < n ; i++)
114         scanf("%lf%lf",&p[i].x,&p[i].y);
115         for(i = 0 ;i < m ;i++)
116         scanf("%lf%lf",&q[i].x,&q[i].y);
117         anticlock(p,n);
118         anticlock(q,m);
119         p[n] = p[0];
120 
121         q[m] = q[0];
122         double ans = min(solve(p,n,q,m),solve(q,m,p,n));
123 
124         printf("%.5f\n",ans);
125     }
126     return 0;
127 }
View Code

 

posted @ 2014-07-30 12:56  _雨  阅读(242)  评论(0编辑  收藏  举报