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
  • 相关阅读:
    Spring--IOC
    神奇的小东西
    视图层发起请求的方式
    jdbc “贾琏欲执事”
    线程的五种状态
    java的<<左移,>>右移,>>>无符号右移
    直接插入排序(单链表排序)
    单链表相关知识以及指针引用相关知识
    将一个数n分解为若干个从小到大排列的质数的积 ,求质数因子
    最小二乘法
  • 原文地址:https://www.cnblogs.com/shangyu/p/3877763.html
Copyright © 2011-2022 走看看