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

 

你可能感兴趣的:(bridge)