题目:Bridge Across Islands

分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696

考虑如下的算法, 算法的输入是两个分别有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.输出最小距离。


 

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h> using namespace std; const int N=50000;
const double eps=1e-9;
const double INF=1e99; struct Point
{
double x,y;
}; Point P[N],Q[N]; double cross(Point A,Point B,Point C)
{
return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
} double dist(Point A,Point B)
{
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
} double multi(Point A,Point B,Point C)
{
return (B.x-A.x)*(C.x-A.x)+(B.y-A.y)*(C.y-A.y);
} //顺时针排序
void anticlockwise(Point p[],int n)
{
for(int i=0;i<n-2;i++)
{
double tmp=cross(p[i],p[i+1],p[i+2]);
if(tmp>eps) return;
else if(tmp<-eps)
{
reverse(p,p+n);
return;
}
}
} //计算C点到直线AB的最短距离
double Getdist(Point A,Point B,Point C)
{
if(dist(A,B)<eps) return dist(B,C);
if(multi(A,B,C)<-eps) return dist(A,C);
if(multi(B,A,C)<-eps) return dist(B,C);
return fabs(cross(A,B,C)/dist(A,B));
} //求一条直线的两端点到另外一条直线的距离,反过来一样,共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 Solve(Point P[],Point Q[],int n,int m)
{
int yminP=0,ymaxQ=0;
for(int i=0;i<n;i++)
if(P[i].y<P[yminP].y)
yminP=i;
for(int i=0;i<m;i++)
if(Q[i].y>Q[ymaxQ].y)
ymaxQ=i;
P[n]=P[0];
Q[m]=Q[0];
double tmp,ans=INF;
for(int i=0;i<n;i++)
{
while(tmp=cross(P[yminP+1],Q[ymaxQ+1],P[yminP])-cross(P[yminP+1],Q[ymaxQ],P[yminP])>eps)
ymaxQ=(ymaxQ+1)%m;
if(tmp<-eps) ans=min(ans,Getdist(P[yminP],P[yminP+1],Q[ymaxQ]));
else ans=min(ans,MinDist(P[yminP],P[yminP+1],Q[ymaxQ],Q[ymaxQ+1]));
yminP=(yminP+1)%n;
}
return ans;
} int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
cin>>P[i].x>>P[i].y;
for(int i=0;i<m;i++)
cin>>Q[i].x>>Q[i].y;
anticlockwise(P,n);
anticlockwise(Q,m);
printf("%.5lf\n",min(Solve(P,Q,n,m),Solve(Q,P,m,n)));
}
return 0;
}

 

POJ3608(旋转卡壳--求两凸包的最近点对距离)的更多相关文章

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

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

  2. 旋转卡壳求两个凸包最近距离poj3608

    #include <iostream> #include <cmath> #include <vector> #include <string.h> # ...

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

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

  4. poj 3608(旋转卡壳求解两凸包之间的最短距离)

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

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

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

  6. POJ2187 旋转卡壳 求最长直径

    给定平面上的一些散点集,求最远两点距离的平方值. 题解: 旋转卡壳求出凸包,然后根据单调性,求出最远两点的最大距离 #pragma GCC optimize(2) #pragma G++ optimi ...

  7. poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方

    旋转卡壳求凸包的直径的平方 板子题 #include<cstdio> #include<vector> #include<cmath> #include<al ...

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

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

  9. UVa 1453 - Squares 旋转卡壳求凸包直径

    旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...

随机推荐

  1. MD5加密简单算法

    public partial class MD5运用 : Form { public MD5运用() { InitializeComponent(); } private void btnChange ...

  2. 关于html的下载功能

    新项目基本告一段落,第一次完成前后端分离的集成,遇到的坑自然不少. 来说说第一天遇到的其中一个坑吧. ——关于下载的问题... 以前的做法,大家都喜爱用<a></a>标签吧.而 ...

  3. ajax分页效果实现

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. Linux下通过shell脚本创建账户

    当我们在linux平台上开发一些项目时,或者有一些项目是需要部署到linux系统上时,有时候会涉及到linux上的特定的账户,例如有一些项目需要运行在某些特定的账户下,或者有时候需要在全新的环境上搭建 ...

  5. 快速搭建Web环境 Angularjs + Express3 + Bootstrap3

    快速搭建Web环境 Angularjs + Express3 + Bootstrap3 AngularJS体验式编程系列文章, 将介绍如何用angularjs构建一个强大的web前端系统.angula ...

  6. H264学习第一篇(编码结构分析)

    学习H264之前,最好阅读一下维基百科中有关H264的相关介绍,里面包含了其的发展历程.主要特点.参考文献.参考网站等. 研究H264的主要文件包括两份参考手册(一份是语法结构参考手册,一份是JM开发 ...

  7. 实现c++的string的split功能

    今天写程序,遇到了一个要实现string.split()这个的一个函数.python里面有,qt里面有,c++里面没有.照着网上抄了一个,放在这里.有需要的时候直接拽过去用,否则老是写了小例子就扔,用 ...

  8. C#向C++编写的DLL传递字符串参数的办法

    使用StringBuilder,举例: C++代码中函数定义如下: PVPOWERFORCASTDLL_API int PVPowerForcast(SForcastInfo &_Forcas ...

  9. MySQL的alter的使用

    ALTER TABLE 语句用于在已有的表中添加.修改或删除列 1.ADD [COLUMN] column name (column definitions) [FIRST or AFTER colu ...

  10. mysql mysqldump只导出表结构或只导出数据的实现方法

    mysql mysqldump只导出表结构或只导出数据的实现方法,需要的朋友可以参考下. mysql mysqldump 只导出表结构 不导出数据 复制代码代码如下: mysqldump --opt ...