Bridge Across Islands
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7202   Accepted: 2113   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 NM. (3 ≤ NM ≤ 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

Source

 
 
 
 
 
经典算法。
 
  1. #include <stdio.h>
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <string.h>
  5. #include <math.h>
  6. using namespace std;
  7.  
  8. const double eps = 1e-;
  9. int sgn(double x)
  10. {
  11. if(fabs(x) < eps)return ;
  12. if(x < )return -;
  13. else return ;
  14. }
  15. struct Point
  16. {
  17. double x,y;
  18. Point(double _x = 0.0,double _y = 0.0)
  19. {
  20. x = _x;
  21. y = _y;
  22. }
  23. Point operator -(const Point &b)const
  24. {
  25. return Point(x - b.x, y - b.y);
  26. }
  27. double operator ^(const Point &b)const
  28. {
  29. return x*b.y - y*b.x;
  30. }
  31. double operator *(const Point &b)const
  32. {
  33. return x*b.x + y*b.y;
  34. }
  35. void input()
  36. {
  37. scanf("%lf%lf",&x,&y);
  38. }
  39. };
  40. struct Line
  41. {
  42. Point s,e;
  43. Line(){}
  44. Line(Point _s,Point _e)
  45. {
  46. s = _s;
  47. e = _e;
  48. }
  49. };
  50. double dist(Point a,Point b)
  51. {
  52. return sqrt((a-b)*(a-b));
  53. }
  54. Point NearestPointToLineSeg(Point P,Line L)
  55. {
  56. Point result;
  57. double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
  58. if(t >= && t <= )
  59. {
  60. result.x = L.s.x + (L.e.x - L.s.x)*t;
  61. result.y = L.s.y + (L.e.y - L.s.y)*t;
  62. }
  63. else
  64. {
  65. if(dist(P,L.s) < dist(P,L.e))
  66. result = L.s;
  67. else result = L.e;
  68. }
  69. return result;
  70. }
  71. /*
  72. * 求凸包,Graham算法
  73. * 点的编号0~n-1
  74. * 返回凸包结果Stack[0~top-1]为凸包的编号
  75. */
  76. const int MAXN = ;
  77. Point list[MAXN];
  78. int Stack[MAXN],top;
  79. //相对于list[0]的极角排序
  80. bool _cmp(Point p1,Point p2)
  81. {
  82. double tmp = (p1-list[])^(p2-list[]);
  83. if(sgn(tmp) > )return true;
  84. else if(sgn(tmp) == && sgn(dist(p1,list[]) - dist(p2,list[])) <= )
  85. return true;
  86. else return false;
  87. }
  88. void Graham(int n)
  89. {
  90. Point p0;
  91. int k = ;
  92. p0 = list[];
  93. //找最下边的一个点
  94. for(int i = ;i < n;i++)
  95. {
  96. if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )
  97. {
  98. p0 = list[i];
  99. k = i;
  100. }
  101. }
  102. swap(list[k],list[]);
  103. sort(list+,list+n,_cmp);
  104. if(n == )
  105. {
  106. top = ;
  107. Stack[] = ;
  108. return;
  109. }
  110. if(n == )
  111. {
  112. top = ;
  113. Stack[] = ;
  114. Stack[] = ;
  115. return ;
  116. }
  117. Stack[] = ;
  118. Stack[] = ;
  119. top = ;
  120. for(int i = ;i < n;i++)
  121. {
  122. while(top > && sgn((list[Stack[top-]]-list[Stack[top-]])^(list[i]-list[Stack[top-]])) <= )
  123. top--;
  124. Stack[top++] = i;
  125. }
  126. }
  127. //点p0到线段p1p2的距离
  128. double pointtoseg(Point p0,Point p1,Point p2)
  129. {
  130. return dist(p0,NearestPointToLineSeg(p0,Line(p1,p2)));
  131. }
  132. //平行线段p0p1和p2p3的距离
  133. double dispallseg(Point p0,Point p1,Point p2,Point p3)
  134. {
  135. double ans1 = min(pointtoseg(p0,p2,p3),pointtoseg(p1,p2,p3));
  136. double ans2 = min(pointtoseg(p2,p0,p1),pointtoseg(p3,p0,p1));
  137. return min(ans1,ans2);
  138. }
  139. //得到向量a1a2和b1b2的位置关系
  140. double Get_angle(Point a1,Point a2,Point b1,Point b2)
  141. {
  142. Point t = b1 - ( b2 - a1 );
  143. return (a2-a1)^(t-a1);
  144. }
  145. //旋转卡壳,求两个凸包的最小距离
  146. double rotating_calipers(Point p[],int np,Point q[],int nq)
  147. {
  148. int sp = , sq = ;
  149. for(int i = ;i < np;i++)
  150. if(sgn(p[i].y - p[sp].y) < )
  151. sp = i;
  152. for(int i = ;i < nq;i++)
  153. if(sgn(q[i].y - q[sq].y) > )
  154. sq = i;
  155. double tmp;
  156. double ans = 1e99;
  157. for(int i = ;i < np;i++)
  158. {
  159. while(sgn(tmp = Get_angle(p[sp],p[(sp+)%np],q[sq],q[(sq+)%nq])) < )
  160. sq = (sq + )%nq;
  161. if(sgn(tmp) == )
  162. ans = min(ans,dispallseg(p[sp],p[(sp+)%np],q[sq],q[(sq+)%nq]));
  163. else ans = min(ans,pointtoseg(q[sq],p[sp],p[(sp+)%np]));
  164. sp = (sp+)%np;
  165. }
  166. return ans;
  167. }
  168.  
  169. double solve(Point p[],int n,Point q[],int m)
  170. {
  171. return min(rotating_calipers(p,n,q,m),rotating_calipers(q,m,p,n));
  172. }
  173. Point p[MAXN],q[MAXN];
  174. int main()
  175. {
  176. int n,m;
  177. while(scanf("%d%d",&n,&m)==)
  178. {
  179. if(n == && m == )break;
  180. for(int i = ;i < n;i++)
  181. list[i].input();
  182. Graham(n);
  183. n = top;
  184. for(int i = ;i < n;i++)
  185. p[i] = list[Stack[i]];
  186. for(int i = ;i < m;i++)
  187. list[i].input();
  188. Graham(m);
  189. m = top;
  190. for(int i = ;i < m;i++)
  191. q[i] = list[Stack[i]];
  192. printf("%.5lf\n",solve(p,n,q,m));
  193. }
  194. return ;
  195. }
 
 
 
 
 

POJ 3608 Bridge Across Islands(旋转卡壳,两凸包最短距离)的更多相关文章

  1. POJ 3608 Bridge Across Islands [旋转卡壳]

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

  2. ●POJ 3608 Bridge Across Islands

    题链: http://poj.org/problem?id=3608 题解: 计算几何,求两个凸包间的最小距离,旋转卡壳 两个凸包间的距离,无非下面三种情况: 所以可以基于旋转卡壳的思想,去求最小距离 ...

  3. POJ 2187 Beauty Contest【旋转卡壳求凸包直径】

    链接: http://poj.org/problem?id=2187 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...

  4. POJ 3608 Bridge Across Islands(计算几何の旋转卡壳)

    Description Thousands of thousands years ago there was a small kingdom located in the middle of the ...

  5. POJ 3608 Bridge Across Islands (旋转卡壳)

    [题目链接] http://poj.org/problem?id=3608 [题目大意] 求出两个凸包之间的最短距离 [题解] 我们先找到一个凸包的上顶点和一个凸包的下定点,以这两个点为起点向下一个点 ...

  6. POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳

    题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...

  7. POJ - 3608 Bridge Across Islands【旋转卡壳】及一些有趣现象

    给两个凸包,求这两个凸包间最短距离 旋转卡壳的基础题 因为是初学旋转卡壳,所以找了别人的代码进行观摩..然而发现很有意思的现象 比如说这个代码(只截取了关键部分) double solve(Point ...

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

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

  9. poj 3608 Bridge Across Islands

    题目:计算两个不相交凸多边形间的最小距离. 分析:计算几何.凸包.旋转卡壳.分别求出凸包,利用旋转卡壳求出对踵点对,枚举距离即可. 注意:1.利用向量法判断旋转,而不是计算角度:避免精度问题和TLE. ...

随机推荐

  1. shell中的IFS和$*变量

    本文转载自http://blog.chinaunix.net/uid-22566367-id-381955.html 自我记录内容.在工程中遇到了相关内容的shell脚本.在此处记录 STRING1= ...

  2. git - 开发者电脑与服务器的配置

    首先公司要有一台git服务器,现在一般都托管在github服务器上,在中国可能会托管到oschina上,oschina有一点好处就是可以免费托管私有项目,而在github上想要托管自己的项目是收费的, ...

  3. JVM对象分配和GC分布【JVM】

    最近在学习java基础结构,刚好学到了jvm,总结了以下并可以结合思维导图认识以下Jvm的对象: 栈:什么是栈? 先说一下栈的数据结构吧,栈它是一种先进后出的数据结构(FILO),跟队列刚好相反(先进 ...

  4. [New learn] 设计模式

    本文翻译自:http://www.raywenderlich.com/46988/ios-design-patterns iOS设计模式 - 你可能听到过这个术语,但是你知道是什么意思吗?虽然大多数的 ...

  5. git学习笔记二-branch分支

    1.刚创建好的空仓库的分支是空的,即使是master分支也是不存在的.master分支是不能通过git branch 来创建的,只有在完成第一次提交才会自动创建,有git自动完成master分子的创建 ...

  6. 关于星号(**/*.java)

    关于星号(**/*.java) (1)前面两个星号(**)表示在项目的所有文件夹(包括子文件夹)中的文件:*.java表示以 .java结尾的所有文件. (2)如果前面两个星号(**)没有,只有星号( ...

  7. kindeditor异步加载 无法初始化

    使用集成的php输出kindeditor无法初始化 function showEditor($id, $value='', $width='700px', $height='300px', $styl ...

  8. 派(Dispatch)

    单派与多派 (Single Dispatch and Multi Dispatch) "检查一个数据项的类型,并据此去调用某个适当的过程称为基于类型的分派". 上面是来自<计 ...

  9. win7家庭版如何获得管理员权限?

    1.首先,打开你的命令提示符,输入cmd.有一点非常重要,如图所示,我们必须“以管理员的方式打开”.只有以管理员身份打开,那么接下来要敲打的命令才会成功. 2. 打开命令提示符后,在输入框输入net ...

  10. 贪心【CF1029E】Tree with Small Distances

    Description 给定一棵树.要求往树中加入一些边使得从1到其他节点的距离至多是2 . 输出加入边的最小数量.(边全部都是无向的) Input 第一行一个整数n,表示树中的节点个数. 接下来n− ...