POJ 3608 Bridge Across Islands(旋转卡壳,两凸包最短距离)
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 7202 | Accepted: 2113 | 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
Source
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std; const double eps = 1e-;
int sgn(double x)
{
if(fabs(x) < eps)return ;
if(x < )return -;
else return ;
}
struct Point
{
double x,y;
Point(double _x = 0.0,double _y = 0.0)
{
x = _x;
y = _y;
}
Point operator -(const Point &b)const
{
return Point(x - b.x, y - b.y);
}
double operator ^(const Point &b)const
{
return x*b.y - y*b.x;
}
double operator *(const Point &b)const
{
return x*b.x + y*b.y;
}
void input()
{
scanf("%lf%lf",&x,&y);
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
};
double dist(Point a,Point b)
{
return sqrt((a-b)*(a-b));
}
Point NearestPointToLineSeg(Point P,Line L)
{
Point result;
double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
if(t >= && t <= )
{
result.x = L.s.x + (L.e.x - L.s.x)*t;
result.y = L.s.y + (L.e.y - L.s.y)*t;
}
else
{
if(dist(P,L.s) < dist(P,L.e))
result = L.s;
else result = L.e;
}
return result;
}
/*
* 求凸包,Graham算法
* 点的编号0~n-1
* 返回凸包结果Stack[0~top-1]为凸包的编号
*/
const int MAXN = ;
Point list[MAXN];
int Stack[MAXN],top;
//相对于list[0]的极角排序
bool _cmp(Point p1,Point p2)
{
double tmp = (p1-list[])^(p2-list[]);
if(sgn(tmp) > )return true;
else if(sgn(tmp) == && sgn(dist(p1,list[]) - dist(p2,list[])) <= )
return true;
else return false;
}
void Graham(int n)
{
Point p0;
int k = ;
p0 = list[];
//找最下边的一个点
for(int i = ;i < n;i++)
{
if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )
{
p0 = list[i];
k = i;
}
}
swap(list[k],list[]);
sort(list+,list+n,_cmp);
if(n == )
{
top = ;
Stack[] = ;
return;
}
if(n == )
{
top = ;
Stack[] = ;
Stack[] = ;
return ;
}
Stack[] = ;
Stack[] = ;
top = ;
for(int i = ;i < n;i++)
{
while(top > && sgn((list[Stack[top-]]-list[Stack[top-]])^(list[i]-list[Stack[top-]])) <= )
top--;
Stack[top++] = i;
}
}
//点p0到线段p1p2的距离
double pointtoseg(Point p0,Point p1,Point p2)
{
return dist(p0,NearestPointToLineSeg(p0,Line(p1,p2)));
}
//平行线段p0p1和p2p3的距离
double dispallseg(Point p0,Point p1,Point p2,Point p3)
{
double ans1 = min(pointtoseg(p0,p2,p3),pointtoseg(p1,p2,p3));
double ans2 = min(pointtoseg(p2,p0,p1),pointtoseg(p3,p0,p1));
return min(ans1,ans2);
}
//得到向量a1a2和b1b2的位置关系
double Get_angle(Point a1,Point a2,Point b1,Point b2)
{
Point t = b1 - ( b2 - a1 );
return (a2-a1)^(t-a1);
}
//旋转卡壳,求两个凸包的最小距离
double rotating_calipers(Point p[],int np,Point q[],int nq)
{
int sp = , sq = ;
for(int i = ;i < np;i++)
if(sgn(p[i].y - p[sp].y) < )
sp = i;
for(int i = ;i < nq;i++)
if(sgn(q[i].y - q[sq].y) > )
sq = i;
double tmp;
double ans = 1e99;
for(int i = ;i < np;i++)
{
while(sgn(tmp = Get_angle(p[sp],p[(sp+)%np],q[sq],q[(sq+)%nq])) < )
sq = (sq + )%nq;
if(sgn(tmp) == )
ans = min(ans,dispallseg(p[sp],p[(sp+)%np],q[sq],q[(sq+)%nq]));
else ans = min(ans,pointtoseg(q[sq],p[sp],p[(sp+)%np]));
sp = (sp+)%np;
}
return ans;
} double solve(Point p[],int n,Point q[],int m)
{
return min(rotating_calipers(p,n,q,m),rotating_calipers(q,m,p,n));
}
Point p[MAXN],q[MAXN];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)==)
{
if(n == && m == )break;
for(int i = ;i < n;i++)
list[i].input();
Graham(n);
n = top;
for(int i = ;i < n;i++)
p[i] = list[Stack[i]];
for(int i = ;i < m;i++)
list[i].input();
Graham(m);
m = top;
for(int i = ;i < m;i++)
q[i] = list[Stack[i]];
printf("%.5lf\n",solve(p,n,q,m));
}
return ;
}
POJ 3608 Bridge Across Islands(旋转卡壳,两凸包最短距离)的更多相关文章
- POJ 3608 Bridge Across Islands [旋转卡壳]
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10455 Accepted: ...
- ●POJ 3608 Bridge Across Islands
题链: http://poj.org/problem?id=3608 题解: 计算几何,求两个凸包间的最小距离,旋转卡壳 两个凸包间的距离,无非下面三种情况: 所以可以基于旋转卡壳的思想,去求最小距离 ...
- POJ 2187 Beauty Contest【旋转卡壳求凸包直径】
链接: http://poj.org/problem?id=2187 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...
- POJ 3608 Bridge Across Islands(计算几何の旋转卡壳)
Description Thousands of thousands years ago there was a small kingdom located in the middle of the ...
- POJ 3608 Bridge Across Islands (旋转卡壳)
[题目链接] http://poj.org/problem?id=3608 [题目大意] 求出两个凸包之间的最短距离 [题解] 我们先找到一个凸包的上顶点和一个凸包的下定点,以这两个点为起点向下一个点 ...
- POJ 3608 Bridge Across Islands --凸包间距离,旋转卡壳
题意: 给你两个凸包,求其最短距离. 解法: POJ 我真的是弄不懂了,也不说一声点就是按顺时针给出的,不用调整点顺序. 还是说数据水了,没出乱给点或给逆时针点的数据呢..我直接默认顺时针给的点居然A ...
- POJ - 3608 Bridge Across Islands【旋转卡壳】及一些有趣现象
给两个凸包,求这两个凸包间最短距离 旋转卡壳的基础题 因为是初学旋转卡壳,所以找了别人的代码进行观摩..然而发现很有意思的现象 比如说这个代码(只截取了关键部分) double solve(Point ...
- poj 3608 Bridge Across Islands 两凸包间最近距离
/** 旋转卡壳,, **/ #include <iostream> #include <algorithm> #include <cmath> #include ...
- poj 3608 Bridge Across Islands
题目:计算两个不相交凸多边形间的最小距离. 分析:计算几何.凸包.旋转卡壳.分别求出凸包,利用旋转卡壳求出对踵点对,枚举距离即可. 注意:1.利用向量法判断旋转,而不是计算角度:避免精度问题和TLE. ...
随机推荐
- Linux 入门记录:六、Linux 硬件相关概念(硬盘、磁盘、磁道、柱面、磁头、扇区、分区、MBR、GPT)
一.硬盘 硬盘的功能相当简单但很重要,它负责记录系统所需要的各种数据.硬盘记录数据有两个方面,一个是硬件方面的存储原理和结构,另外一方面则是软件方面的数据和文件系统.硬盘的主要行为就是数据的存放和取出 ...
- Linux Python apache的cgi配置
一.找到安装Apache的目录/usr/local/apache2/conf,并对httpd.conf配置文件进行修改 1.加载cgi模块 去掉注释: LoadModule cgid_module m ...
- linux命令(3):rpm命令
查询当前环境是否已安装软件包,如下命令: [root@cloud ~]# rpm -qa | grep httpd httpd-2.4.6-31.el7.centos.1.x86_64 httpd-t ...
- 阿里云Centos等更新源设置成阿里源方法。
https://help.aliyun.com/knowledge_detail/5974184.html ---------------------------------------------- ...
- 深度学习方法:受限玻尔兹曼机RBM(一)基本概念
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 最近在复习经典机器学习算法的同 ...
- Path Sum I&&II
I Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...
- es6扩展运算符及rest运算符总结
扩展运算符(...) 1.如果一个函数的参数个数不确定,可以用其代替 eg:求若干个数的和 2.改数组的引用为复制一份内存 此刻数组a也发生了变化,因为数组b是a的一个引用 此刻相当于复制了一份a 3 ...
- react native android 应用状态(前端或后台)的判断
当Android应用程序被暂时放到了后台,或者又重新回到前台,是否有相应的事件可以处理到? 例如,当你的应用暂时放到了后台,是否应该做出一些操作,暂时保存界面上的数据? 可以参考:https://gi ...
- Power BI连接至Mogo Altas Connector For BI
我需要使用Power BI连接至Connector For BI ,现在Connect For BI存放在Mongo Atlas中,详细的来自于官方文档,https://docs.atlas.mong ...
- 洛谷P2168 [NOI2015] 荷马史诗 [哈夫曼树]
题目传送门 荷马史诗 Description 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马 ...