poj3608Bridge Across Islands(凸包间最小距离)
以下所有文章均转载( http://blog.csdn.net/acmaker/article/details/3176910) 转载请注明出处!
考虑如下的算法, 算法的输入是两个分别有 m 和 n 个顺时针给定顶点的凸多边形 P 和 Q。
- 计算 P 上 y 坐标值最小的顶点(称为 yminP ) 和 Q 上 y 坐标值最大的顶点(称为 ymaxQ)。
- 为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧。 此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和 ymaxQ 成为了多边形间的一个对踵点对。
- 计算距离(yminP,ymaxQ) 并且将其维护为当前最小值。
- 顺时针同时旋转平行线直到其中一个与其所在的多边形的边重合。
- 如果只有一条线与边重合, 那么只需要计算“顶点-边”对踵点对和“顶点-顶点”对踵点对距离。 都将他们与当前最小值比较, 如果小于当前最小值则进行替换更新。 如果两条切线都与边重合, 那么情况就更加复杂了。 如果边“交叠”, 也就是可以构造一条与两条边都相交的公垂线(但不是在顶点处相交), 那么就计算“边-边”距离。 否则计算三个新的“顶点-顶点”对踵点对距离。 所有的这些距离都与当前最小值进行比较, 若小于当前最小值则更新替换。
- 重复执行步骤4和步骤5, 直到新的点对为(yminP,ymaxQ)。
- 输出最大距离。
以上是转载。。以下是原创。。
上面是按顺时针存的凸包也是按顺时针旋转的平行线,网上很多是逆时针的凸包却写着顺时针的做法,但代码依旧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(凸包间最小距离)的更多相关文章
- POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳
题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...
- poj 3608 凸包间的最小距离
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7632 Accepted: ...
- poj 3608 Bridge Across Islands 两凸包间最近距离
/** 旋转卡壳,, **/ #include <iostream> #include <algorithm> #include <cmath> #include ...
- POJ 3608 凸包间最短距离(旋转卡壳)
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11539 Accepted: ...
- 图算法之Floyd-Warshall 算法-- 任意两点间最小距离
1.Floyd-Warshall 算法 给定一张图,在o(n3)时间内求出任意两点间的最小距离,并可以在求解过程中保存路径 2.Floyd-Warshall 算法概念 这是一个动态规划的算法. 将顶点 ...
- POJ 3608 Bridge Across Islands(旋转卡壳,两凸包最短距离)
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7202 Accepted: ...
- UVa1453或La4728 凸包+枚举(或旋转卡壳)
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- poj 2187 凸包加旋转卡壳算法
题目链接:http://poj.org/problem?id=2187 旋转卡壳算法:http://www.cppblog.com/staryjy/archive/2009/11/19/101412. ...
- ●POJ 3608 Bridge Across Islands
题链: http://poj.org/problem?id=3608 题解: 计算几何,求两个凸包间的最小距离,旋转卡壳 两个凸包间的距离,无非下面三种情况: 所以可以基于旋转卡壳的思想,去求最小距离 ...
随机推荐
- 编译器 perforSelecter时 警告去除
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks&quo ...
- Window驱动开发
驱动开发 参考文章: Windbg+Vmware驱动调试 http://blog.csdn.net/xuepiaosong/article/details/8236702 驱动调试攻略(WinDbg) ...
- java 判断某一天是当年的哪一天
题目:输入年份,月份,日,判断这一天是这一年的第几天?(闰年的2月份为29天,平年为28天) public class Runnian { /** * 能被4整除且不能被100整除或者能被400整除的 ...
- 在IE6下使用filter设置png背景
今天帮别人解决问题学会了一个在IE6下使用filter设置png背景,具体css写法如下: .login_form_wrap { width: 778px; height: 360px; backgr ...
- Improving the GPA 分类: 贪心 HDU 比赛 2015-08-08 16:12 11人阅读 评论(0) 收藏
Improving the GPA Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- MySQL bin-log 日志清理方式
MySQL bin-log 作用 1.数据恢复:如果你的数据库出问题了,而你之前有过备份,那么可以看日志文件,找出是哪个命令导致你的数据库出问题了,想办法挽回损失. 2.主从服务器之间同步数据:主 ...
- Python_cmd的各种实现方法及优劣(subprocess.Popen, os.system和commands.getstatusoutput)
http://blog.csdn.net/menglei8625/article/details/7494094
- mongodb(4查询)
第一个参数决定要返回那些文档 db.test.find()返回所有文档 db.test.find({"age":27}) db.test.find({"username& ...
- 最小化安装centos的init初始化脚本
#!/bin/bash #this script is appropriate .x(这脚本适合最小化安装6.x版本的系统) #you have already install the os read ...
- OS开发(Objective-C)常用库索引
code4app.com 这网站不错,收集各种 iOS App 开发可以用到的代码示例 cocoacontrols.com/ 英文版本的lib收集 objclibs.com/ 精品lib的收集网站 h ...