链接

以下所有文章均转载( http://blog.csdn.net/acmaker/article/details/3176910) 转载请注明出处!

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

以上是转载。。以下是原创。。

上面是按顺时针存的凸包也是按顺时针旋转的平行线,网上很多是逆时针的凸包却写着顺时针的做法,但代码依旧A了,,不是很理解。。

逆时针 改反一点 依旧A。。。

感觉自己 的是对的吧。。。

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 10010
#define LL long long
#define INF 0xfffffff
const double eps = 1e-;
const double pi = acos(-1.0);
const double inf = ~0u>>;
struct Point
{
double x,y;
Point(double x=,double y=):x(x),y(y) {} //构造函数 方便代码编写
}p[N],q[N];
typedef Point pointt;
pointt operator + (Point a,Point b)
{
return Point(a.x+b.x,a.y+b.y);
}
pointt operator - (Point a,Point b)
{
return Point(a.x-b.x,a.y-b.y);
}
int dcmp(double x)
{
if(fabs(x)<eps) return ;
else return x<?-:;
}
bool operator == (const Point &a,const Point &b)
{
return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;
}
double dot(Point a,Point b)
{
return a.x*b.x+a.y*b.y;
}
double dis(Point a)
{
return sqrt(dot(a,a));
}
double cross(Point a,Point b)
{
return a.x*b.y-a.y*b.x;
}
void anticlock(Point p[],int n)
{
for(int i = ; i < n- ; i++)
{
double k = cross(p[i+]-p[],p[i+]-p[]);
if(dcmp(k)>) return ;
else if(dcmp(k)<)
{
reverse(p,p+n);
return ;
}
}
}
double distoline(Point a,Point b,Point c)
{
if(dcmp(dis(a-b))==) return dis(a-c);
if(dcmp(dot(a-b,a-c))<) return dis(a-c);
if(dcmp(dot(b-a,b-c))<) return dis(b-c);
return fabs(cross(a-b,a-c))/dis(a-b);
}
double dist(Point a,Point b,Point c,Point d)
{
double ans = distoline(a,b,c);
ans = min(ans,distoline(a,b,d));
ans = min(ans,distoline(c,d,a));
ans = min(ans,distoline(c,d,b));
return ans;
}
double mul(Point a,Point b,Point c)
{
return cross(b-a,c-a);
}
double solve(Point p[],int n,Point q[],int m)
{
int i;
int miny = ,maxy = ;
for(i = ;i < n; i++)
{
if(p[i].y<p[miny].y)
miny = i;
}
for(i = ; i< m ; i++)
if(q[i].y>q[maxy].y) maxy = i;
double ans = dis(p[miny]-q[maxy]);
for(i = ;i < n; i++)
{
double tmp;
while(tmp = mul(p[miny],p[miny+],q[maxy+])-mul(p[miny],p[miny+],q[maxy])>eps)
maxy = (maxy+)%m;
if(dcmp(tmp)>) ans = min(ans,distoline(p[miny],p[miny+],q[maxy]));//这里如果写成<0 画图可以看出是顺时针的做法 就算不加这句直接算下面的也能A。。
else
ans = min(ans,dist(p[miny],p[miny+],q[maxy],q[maxy+]));//边-边
miny = (miny+)%n;
}
return ans;
}
int main()
{
int i,n,m;
while(scanf("%d%d",&n,&m)&&n&&m)
{
for(i = ; i < n ; i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for(i = ;i < m ;i++)
scanf("%lf%lf",&q[i].x,&q[i].y);
anticlock(p,n);
anticlock(q,m);
p[n] = p[]; q[m] = q[];
double ans = min(solve(p,n,q,m),solve(q,m,p,n)); printf("%.5f\n",ans);
}
return ;
}

poj3608Bridge Across Islands(凸包间最小距离)的更多相关文章

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

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

  2. poj 3608 凸包间的最小距离

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

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

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

  4. POJ 3608 凸包间最短距离(旋转卡壳)

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

  5. 图算法之Floyd-Warshall 算法-- 任意两点间最小距离

    1.Floyd-Warshall 算法 给定一张图,在o(n3)时间内求出任意两点间的最小距离,并可以在求解过程中保存路径 2.Floyd-Warshall 算法概念 这是一个动态规划的算法. 将顶点 ...

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

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

  7. UVa1453或La4728 凸包+枚举(或旋转卡壳)

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  8. poj 2187 凸包加旋转卡壳算法

    题目链接:http://poj.org/problem?id=2187 旋转卡壳算法:http://www.cppblog.com/staryjy/archive/2009/11/19/101412. ...

  9. ●POJ 3608 Bridge Across Islands

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

随机推荐

  1. 错误: 找不到或无法加载主类 Files\apache-activemq-5.10.0\bin\..\conf\login.config

    在启动activemq的时候出现错误:“错误: 找不到或无法加载主类 Files\apache-activemq-5.10.0\bin\..\conf\login.config”,之前用activem ...

  2. Eclipse中Outline里各种图标的含义

    在使用Eclipse或者MyEclipse开发的时候,你一定看到过Outline和Package Explorer中小图标,很多刚刚接触编程的童鞋们可能不会在意它们代表的含义,但如果你花几分钟的时间了 ...

  3. Apache2.2 + php-5.4.45-Win32-VC9-x86 配置

    首先要注意一个问题是:网上有很多教程比如: 在Apache配置文件中添加php模块.在apache2\conf\httpd.conf中: LoadModule模块添加行: LoadModule php ...

  4. CodeBlocks养眼的colour theme

    把如下的代码复制粘贴到这个文件:default.conf <?xml version="1.0" encoding="UTF-8" standalone= ...

  5. 为测试框架model类自动生成xml结果集

    问题:有大量类似于theProductId这样名字的字符串需要转换成the_product_id这种数据库column名的形式. 思路:见到(见)大写字母(缝)就插入(插)一个“_”字符(针)进去,最 ...

  6. java的myeclipse生成webservice的service和client

    前言:朋友们开始以下教程前,请先看第五大点的注意事项,以避免不必要的重复操作. 一.准备工作(以下为本实例使用工具) 1.MyEclipse10.7.1 2.JDK 1.6.0_22 二.创建服务端 ...

  7. Android WebView使用基础

    WebView基本使用 WebView是View的一个子类,可以让你在activity中显示网页. 可以在布局文件中写入WebView:比如下面这个写了一个填满整个屏幕的WebView: <?x ...

  8. 修改idea的运行内存

    1.如果本地的jdk是32位的,那么最大的内存只能支持到1024 2.测试jdk位数 public class Test { public static void main(String[] args ...

  9. linux 强大的编辑器之vi

    vi编辑器是一个处理ASCII数据的文本工具.大多数linux发行版都已经默认安装了vi编辑器.vi是visual interface的缩写vim是 visual interface improved ...

  10. sql 邮件发送测试情况

    sql 邮件发送测试情况 select * from msdb.dbo.sysmail_allitems select * from msdb.dbo.sysmail_event_log