zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    125     }
    126     return 0;
    127 }
    View Code
  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/shangyu/p/3877763.html
Copyright © 2011-2022 走看看