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. HDU 1398 Square Coins 整数拆分变形 母函数

    欢迎参加——BestCoder周年纪念赛(高质量题目+多重奖励) Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit ...

  2. C++版本的C标准库头文件的特点

    C++标准库中除了定义C++语言特有的功能外,也兼容了C语言的标准库.C语言的头文件形如name.h,C++则将这些文件命名为cname.也就是去掉了.h后缀,而在文件名name之前添加了字母c,这里 ...

  3. 结对作业 -GUI四则运算

    目录: 一.前言(及项目地址) 二.PSP(planning) 三.结对编程中对接口的设计 四.计算模块接口的设计与实现过程 五.计算模块接口部分的性能改进 六.计算模块部分单元测试展示 七.计算模块 ...

  4. jcaptcha配置验证码

    准备开始 首先导入jar包:jcaptcha-my-1.0 /** * web 常量 * @author lx * */ public abstract class Constants { /** 用 ...

  5. 【bzoj3043】IncDec Sequence 差分

    题目描述 给定一个长度为n的数列{a1,a2...an},每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一.问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下 ...

  6. LeetCode -- Linked List Circle ii

    Question: Given a linked list, return the node where the cycle begins. If there is no cycle, return  ...

  7. HDU 6203 ping ping ping(贪心+LCA+DFS序+BIT)

    ping ping ping Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. 2018宁夏邀请赛L Continuous Intervals

    题目链接:https://nanti.jisuanke.com/t/28412 题意: 给出n个数的序列.问序列中有多少个区间满足,排序完之后任意两个相邻的数之差不大于1. 题解: 用max表示区间最 ...

  9. nginx 静态文件支持跨域访问权限

    一.原生态 location ^~ /repurchase-web/ {          alias /var/www/webapps/repurchase-web/;        } 二.支持跨 ...

  10. 问题总结——window平台下grunt\bower安装后无法运行的问题

    一.问题: 安装grunt或者bower后,在cmd控制台运行grunt -version 或者 bower -v会出现:“xxx不是内部或外部命令,也不是可运行的程序或批处理文件”,