Bridge Across Islands
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9768   Accepted: 2866   Special Judge

Description

Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory of the kingdom consists two separated islands. Due to the impact of the ocean current, the shapes of both the islands became convex polygons. The king of the kingdom wanted to establish a bridge to connect the two islands. To minimize the cost, the king asked you, the bishop, to find the minimal distance between the boundaries of the two islands.

Input

The input consists of several test cases.
Each test case begins with two integers N, M. (3 ≤ N, M ≤ 10000)
Each of the next N lines contains a pair of coordinates, which describes the position of a vertex in one convex polygon.
Each of the next M lines contains a pair of coordinates, which describes the position of a vertex in the other convex polygon.
A line with N = M = 0 indicates the end of input.
The coordinates are within the range [-10000, 10000].

Output

For each test case output the minimal distance. An error within 0.001 is acceptable.

Sample Input

  1. 4 4
  2. 0.00000 0.00000
  3. 0.00000 1.00000
  4. 1.00000 1.00000
  5. 1.00000 0.00000
  6. 2.00000 0.00000
  7. 2.00000 1.00000
  8. 3.00000 1.00000
  9. 3.00000 0.00000
  10. 0 0

Sample Output

  1. 1.00000
  2.  
  3. 引自:http://blog.csdn.net/acmaker/article/details/3178696
    两个凸多边形 P Q 之间的最小距离由多边形间的对踵点对确立。 存在凸多边形间的三种多边形间的对踵点对, 因此就有三种可能存在的最小距离模式:
  1. “顶点-顶点”的情况
  2. “顶点-边”的情况
  3. “边-边”的情况
  1. 换句话说, 确定最小距离的点对不一定必须是顶点。 下面的三个图例表明了以上结论: 

  1.  

  1.  

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

模板如下:

  1. /*
  2. 叉积的一个非常重要的性质是可以通过它的符号来判断两矢量相互之间的顺逆时针关系:
  3. 若 P * Q > 0,则 P 在 Q 的顺时针方向;
  4. 若 P * Q < 0, 则 P 在 Q 的逆时针方向;
  5. 若 P * Q = 0,则 P 与 Q 共线,但不确定 P, Q 的方向是否相同;
  6. */
  7. #include <iostream>
  8. #include <cstdio>
  9. #include <cstring>
  10. #include <math.h>
  11. #include <algorithm>
  12. using namespace std;
  13. const double esp = 1e-;
  14. const int N = ;
  15. struct Point
  16. {
  17. double x,y;
  18. } p[N],q[N];
  19. int n,m;
  20. ///叉积
  21. double mult_cross(Point a,Point b,Point c)
  22. {
  23. return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
  24. }
  25. ///点积
  26. double mult_point(Point a,Point b,Point c){
  27. return (a.x-c.x)*(b.x-c.x)+(a.y-c.y)*(b.y-c.y);
  28. }
  29. ///距离
  30. double dis(Point a,Point b)
  31. {
  32. return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
  33. }
  34. ///将点集按照逆时钟排序
  35. void clockwise_sort(Point p[],int n){
  36. for(int i=;i<n-;i++){
  37. double tmp = mult_cross(p[i+],p[i+],p[i]);
  38. if(tmp>) return;
  39. else if(tmp<){
  40. reverse(p,p+n);
  41. return;
  42. }
  43. }
  44. }
  45. ///点c到直线ab的最短距离
  46. double GetDist(Point a,Point b,Point c){
  47. if(dis(a,b)<esp) return dis(b,c); ///a,b是同一个点
  48. if(mult_point(b,c,a)<-esp) return dis(a,c); ///投影
  49. if(mult_point(a,c,b)<-esp) return dis(b,c);
  50. return fabs(mult_cross(b,c,a)/dis(a,b));
  51.  
  52. }
  53. ///求一条线段ab的两端点到另外一条线段bc的距离,反过来一样,共4种情况
  54. double MinDist(Point a,Point b,Point c,Point d){
  55. return min(min(GetDist(a,b,c),GetDist(a,b,d)),min(GetDist(c,d,a),GetDist(c,d,b)));
  56. }
  57.  
  58. double min_PQ(Point p[],Point q[],int n,int m){
  59. int yminP = ,ymaxQ=;
  60. for(int i=;i<n;i++){ ///找到点集p组成的凸包的左下角
  61. if(p[i].y<p[yminP].y||(p[i].y==p[yminP].y)&&(p[i].x<p[yminP].x)) yminP = i;
  62. }
  63. for(int i=;i<m;i++){ ///找到点集q组成的凸包的右上角
  64. if(q[i].y>q[ymaxQ].y||(q[i].y==q[ymaxQ].y)&&(q[i].x>q[ymaxQ].x)) ymaxQ = i;
  65. }
  66. double ans = dis(p[yminP],q[ymaxQ]); ///距离(yminP,ymaxQ)维护为当前最小值。
  67. p[n]=p[],q[m]=q[];
  68. for(int i=;i<n;i++){
  69. double tmp;
  70. while(tmp=(mult_cross(q[ymaxQ+],p[yminP],p[yminP+])-mult_cross(q[ymaxQ],p[yminP],p[yminP+]))>esp)
  71. ymaxQ = (ymaxQ+)%m;
  72. if(tmp<-esp) ans = min(ans,GetDist(p[yminP],p[yminP+],q[ymaxQ]));
  73. else ans=min(ans,MinDist(p[yminP],p[yminP+],q[ymaxQ],q[ymaxQ+]));
  74. yminP = (yminP+)%n;
  75. }
  76. return ans;
  77. }
  78. int main()
  79. {
  80. while(scanf("%d%d",&n,&m)!=EOF,n+m)
  81. {
  82. for(int i=; i<n; i++)
  83. {
  84. scanf("%lf%lf",&p[i].x,&p[i].y);
  85. }
  86. for(int i=; i<m; i++)
  87. {
  88. scanf("%lf%lf",&q[i].x,&q[i].y);
  89. }
  90. clockwise_sort(p,n);
  91. clockwise_sort(q,m);
  92. double ans = min(min_PQ(p,q,n,m),min_PQ(q,p,m,n));
  93. printf("%.5lf\n",ans);
  94. }
  95. return ;
  96. }

poj 3608(旋转卡壳求解两凸包之间的最短距离)的更多相关文章

  1. poj 3608 旋转卡壳求不相交凸包最近距离;

    题目链接:http://poj.org/problem?id=3608 #include<cstdio> #include<cstring> #include<cmath ...

  2. POJ 3608 Bridge Across Islands(旋转卡壳,两凸包最短距离)

    Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7202   Accepted:  ...

  3. poj 2079(旋转卡壳求解凸包内最大三角形面积)

    Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 9060   Accepted: 2698 Descript ...

  4. Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

    \(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...

  5. 「POJ-3608」Bridge Across Islands (旋转卡壳--求两凸包距离)

    题目链接 POJ-3608 Bridge Across Islands 题意 依次按逆时针方向给出凸包,在两个凸包小岛之间造桥,求最小距离. 题解 旋转卡壳的应用之一:求两凸包的最近距离. 找到凸包 ...

  6. poj 3608 Bridge Across Islands 两凸包间最近距离

    /** 旋转卡壳,, **/ #include <iostream> #include <algorithm> #include <cmath> #include ...

  7. POJ 3608 旋转卡壳

    思路: 旋转卡壳应用 注意点&边  边&边  点&点 三种情况 //By SiriusRen #include <cmath> #include <cstdi ...

  8. POJ3608(旋转卡壳--求两凸包的最近点对距离)

    题目:Bridge Across Islands 分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696 考虑如下的算法, 算法的 ...

  9. Poj 2187 旋转卡壳

    Poj 2187 旋转卡壳求解 传送门 旋转卡壳,是利用凸包性质来求解凸包最长点对的线性算法,我们逐渐改变每一次方向,然后枚举出这个方向上的踵点对(最远点对),类似于用游标卡尺卡着凸包旋转一周,答案就 ...

随机推荐

  1. # ML学习小笔记—Gradien Descent

    关于本课程的相关资料http://speech.ee.ntu.edu.tw/~tlkagk/courses_ML17.html 根据前面所为,当我们得到Loss方程的时候,我们希望求得最优的Loss方 ...

  2. vue-cli项目里npm安装font-awesome

    第一步:进入到项目目录里,运行 cnpm i font-awesome -s 第二步:在main.js里面 import 'font-awesome/css/font-awesome.min.css'

  3. perf 对两个map是否重叠的判断,以及函数map_groups__fixup_overlappings代码逻辑

    该标题可以抽象出来的问题是:两个前开后闭的区间 rangeA 和 rangeB,如何判断这两个区间是否重叠.这个问题在内核中非常重要,虚拟地址空间的划分需要它,perf中map_group的构建也需要 ...

  4. shit element ui & form password validation

    shit element ui & form password validation shit docs https://github.com/yiminghe/async-validator ...

  5. oracle 引用类型声明

  6. 习题:就是干(DP)

    洛谷2301 题目描述 眼看着老师大军浩浩荡荡的向机房前进.LOI 的同学们决定动用自己的力量来保卫他们的好朋友loidc.现在每个人都要挑选自己的武器——两根木棍.一根用做远距离投掷,另一根用做近距 ...

  7. Springboot2.0 集成shiro权限管理

    在springboot中结合shiro教程搭建权限管理,其中几个小细节的地方对新手不友好,伸手党更是无法直接运行代码,搭建过程容易遇坑,记录一下.关键的地方也给注释了. 版本:springboot版本 ...

  8. [HAOI2010]计数

    题面在这里 description 你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数. 比如说给定{1,2},那么可以生成数字12,21,102,120,201,210 ...

  9. [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania

    [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...

  10. uva10884 Persephone

    题目戳这里. 找规律. 每一列占据的格子一定是一段区间: 相邻列之间的区间有交. 上界先增后减,下界先减后增. \(f_{i,j,k,0/1,0/1}\)表示考虑前\(i\)列,第\(i\)列,上界为 ...