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

4 4
0.00000 0.00000
0.00000 1.00000
1.00000 1.00000
1.00000 0.00000
2.00000 0.00000
2.00000 1.00000
3.00000 1.00000
3.00000 0.00000
0 0

Sample Output

1.00000

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

 

 

给定结果, 一个基于旋转卡壳的算法自然而然的产生了: 
考虑如下的算法, 算法的输入是两个分别有 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. 输出最小距离。

模板如下:

/*
叉积的一个非常重要的性质是可以通过它的符号来判断两矢量相互之间的顺逆时针关系:
若 P * Q > 0,则 P 在 Q 的顺时针方向;
若 P * Q < 0, 则 P 在 Q 的逆时针方向;
若 P * Q = 0,则 P 与 Q 共线,但不确定 P, Q 的方向是否相同;
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
const double esp = 1e-;
const int N = ;
struct Point
{
double x,y;
} p[N],q[N];
int n,m;
///叉积
double mult_cross(Point a,Point b,Point c)
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
///点积
double mult_point(Point a,Point b,Point c){
return (a.x-c.x)*(b.x-c.x)+(a.y-c.y)*(b.y-c.y);
}
///距离
double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
///将点集按照逆时钟排序
void clockwise_sort(Point p[],int n){
for(int i=;i<n-;i++){
double tmp = mult_cross(p[i+],p[i+],p[i]);
if(tmp>) return;
else if(tmp<){
reverse(p,p+n);
return;
}
}
}
///点c到直线ab的最短距离
double GetDist(Point a,Point b,Point c){
if(dis(a,b)<esp) return dis(b,c); ///a,b是同一个点
if(mult_point(b,c,a)<-esp) return dis(a,c); ///投影
if(mult_point(a,c,b)<-esp) return dis(b,c);
return fabs(mult_cross(b,c,a)/dis(a,b)); }
///求一条线段ab的两端点到另外一条线段bc的距离,反过来一样,共4种情况
double MinDist(Point a,Point b,Point c,Point d){
return min(min(GetDist(a,b,c),GetDist(a,b,d)),min(GetDist(c,d,a),GetDist(c,d,b)));
} double min_PQ(Point p[],Point q[],int n,int m){
int yminP = ,ymaxQ=;
for(int i=;i<n;i++){ ///找到点集p组成的凸包的左下角
if(p[i].y<p[yminP].y||(p[i].y==p[yminP].y)&&(p[i].x<p[yminP].x)) yminP = i;
}
for(int i=;i<m;i++){ ///找到点集q组成的凸包的右上角
if(q[i].y>q[ymaxQ].y||(q[i].y==q[ymaxQ].y)&&(q[i].x>q[ymaxQ].x)) ymaxQ = i;
}
double ans = dis(p[yminP],q[ymaxQ]); ///距离(yminP,ymaxQ)维护为当前最小值。
p[n]=p[],q[m]=q[];
for(int i=;i<n;i++){
double tmp;
while(tmp=(mult_cross(q[ymaxQ+],p[yminP],p[yminP+])-mult_cross(q[ymaxQ],p[yminP],p[yminP+]))>esp)
ymaxQ = (ymaxQ+)%m;
if(tmp<-esp) ans = min(ans,GetDist(p[yminP],p[yminP+],q[ymaxQ]));
else ans=min(ans,MinDist(p[yminP],p[yminP+],q[ymaxQ],q[ymaxQ+]));
yminP = (yminP+)%n;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF,n+m)
{
for(int i=; i<n; i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
for(int i=; i<m; i++)
{
scanf("%lf%lf",&q[i].x,&q[i].y);
}
clockwise_sort(p,n);
clockwise_sort(q,m);
double ans = min(min_PQ(p,q,n,m),min_PQ(q,p,m,n));
printf("%.5lf\n",ans);
}
return ;
}

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. beta版本冲刺四

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组 ...

  2. PowerDesigner工具箱(palette)关了如何重新打开

    PowerDesigner的设计工具箱palette,palette的实际意思:颜料.调色板 工具箱关闭了 重新打开的方法其实很简单的,贴几张图片上来,帮助一下大家 方法一: 在工具栏的空白处点击鼠标 ...

  3. springboot ueditor 使用心得

    1.将ueditor引入项目中会发现,图片不能上传,返回值意思是因配置文件错误,导致图片无法上传 默认情况是使用jsp初始配置文件,这就需要项目支持jsp解析 在maven中引入 <!--添加对 ...

  4. jsp中的session和上下文

    Session的典型应用: 防止用户非法登录到某个页面. 网上商城的购物车 保存用户登录信息 注:多个请求要用的东西放在session中,多个会话之间要用的东西放在上下文中. 如何创建session? ...

  5. BZOJ4602 SDOI2016齿轮(搜索)

    dfs一遍给每个齿轮随便标个值看是否矛盾就行了. #include<iostream> #include<cstdio> #include<cmath> #incl ...

  6. Ural 1297 Palindrome(Manacher或者后缀数组+RMQ-ST)

    1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB The “U.S. Robots” HQ has just received a ...

  7. 【考试记录】4.8 Table ( 数论数学 --组合数 & 杨辉三角)

    陆陆续续的开始考很多的试,也会更新这些题目记录下来,免得做完了之后毫无印象,就这么水过去了(以前的考试都是如此,哎……) Table (T1) : 样例: 出于对数学题本能的恐惧考场上放弃了此题专攻T ...

  8. luogu P2764 最小路径覆盖问题

    题目描述 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任 ...

  9. POJ3189:Steady Cow Assignment(二分+二分图多重匹配)

    Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7482   Accepted: ...

  10. 编写clearedit的安卓控件

    1.写一个自定义的控件 public class ClearEditText extends AppCompatEditText implements View.OnFocusChangeListen ...