poj 3608 Bridge Across Islands
题目:计算两个不相交凸多边形间的最小距离。
分析:计算几何、凸包、旋转卡壳。分别求出凸包,利用旋转卡壳求出对踵点对,枚举距离即可。
注意:1.利用向量法判断旋转,而不是计算角度;避免精度问题和TLE。
2.遇到平行线段时,需要计算4组点到线段距离,不然会漏掉对踵点对。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath> using namespace std; //点结构
typedef struct pnode
{
double x,y,d;
pnode( double a, double b ) {x = a;y = b;}
pnode(){};
}point;
point T,P[10005],Q[10005]; //线段结构
typedef struct lnode
{
double x,y,dx,dy;
lnode( point a, point b ) {x = a.x;y = a.y;dx = b.x-a.x;dy = b.y-a.y;}
lnode(){};
}line; //叉乘 ab*ac
double crossproduct( point a, point b, point c )
{
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
} //两点间距离
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 dist( point a, point p, point q )
{
line l = line( p, q );
//判断垂足位置
if ( (l.dx*(p.x-a.x)+l.dy*(p.y-a.y))*(l.dx*(q.x-a.x)+l.dy*(q.y-a.y)) < 0 )
return fabs(l.dx*(a.y-l.y)-l.dy*(a.x-l.x))/sqrt(l.dx*l.dx+l.dy*l.dy);
else return min( dist( a, p ), dist( a, q ) );
} //坐标比较
bool cmp1( point a, point b )
{
return (a.x==b.x)?(a.y<b.y):(a.x<b.x);
} //级角比较
bool cmp2( point a, point b )
{
double cp = crossproduct( T, a, b );
if ( !cp ) return a.d < b.d;
else return cp > 0;
} //凸包
int graham( point* p, int n )
{
sort( p+0, p+n, cmp1 );
for ( int i = 1 ; i < n ; ++ i )
p[i].d = dist( p[0], p[i] );
T = p[0];
sort( p+1, p+n, cmp2 ); int top = 1;
for ( int i = 2 ; i < n ; ++ i ) {
while ( top > 0 && crossproduct( p[top-1], p[top], p[i] ) <= 0 ) -- top;
p[++ top] = p[i];
}
p[++ top] = p[0]; return top;
} //利用向量判断夹角
double judge( point a, point b, point c, point d )
{
return crossproduct( c, d, point( c.x+b.x-a.x, c.y+b.y-a.y ) );
} //旋转卡壳
double rotatingcalipers( point* p, point* q, int n, int m )
{
double D = 30000.0;
int R = 0;
for ( int i = 0 ; i < m ; ++ i )
if ( q[i].x >= q[R].x ) R = i;
for ( int L = 0 ; L < n ; ++ L ) {
while ( judge( p[L], p[L+1], q[R], q[R+1] ) < 1e-6 )
R = (R+1)%m;
//两条边平行时,需计算平行线段间最短距离,即四个点到线段的距离
D = min( min( D, dist( p[L], q[R] ) ),
min( min( dist( p[L], q[R], q[R+1] ), dist( q[R], p[L], p[L+1] ) ),
min( dist( p[L+1], q[R], q[R+1] ), dist( q[R+1], p[L], p[L+1] ) ) ) );
} return D;
} int main()
{
int N,M;
while ( scanf("%d%d",&N,&M) && N ) {
for ( int i = 0 ; i < N ; ++ i )
scanf("%lf%lf",&P[i].x,&P[i].y);
for ( int i = 0 ; i < M ; ++ i )
scanf("%lf%lf",&Q[i].x,&Q[i].y); N = graham( P, N );
M = graham( Q, M ); printf("%.5lf\n",rotatingcalipers( P, Q, N, M ));
}
return 0;
}
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(旋转卡壳,两凸包最短距离)
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7202 Accepted: ...
- ●POJ 3608 Bridge Across Islands
题链: http://poj.org/problem?id=3608 题解: 计算几何,求两个凸包间的最小距离,旋转卡壳 两个凸包间的距离,无非下面三种情况: 所以可以基于旋转卡壳的思想,去求最小距离 ...
- 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 3068 Bridge Across Islands
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11196 Accepted: ...
随机推荐
- mysql 事务类型表的用法
mysql关联表(references)的条件:1.两个表必须是 InnoDB表类型2.使用在外键关系的域必须为索引型(Index)3.使用外键关系的域必须与数据类型相似 以下是父表和子表的例子:创建 ...
- c#面向对象小结
特点: 1:将复杂的事情简单化. 2:面向对象将以前的过程中的执行者,变成了指挥者. 3:面向对象这种思想是符合现在人们思考习惯的一种思想. 过程和对象在我们的程序中是如何体现的呢?过程其实就是函数: ...
- tr设置border无效的解决方法
给table的css添加属性:border-collapse: collapse; 边框不折叠的表格 行,列,行组是不具有border的
- python 数据类型(元组(不可变列表),字符串
元组(不可变列表) 创建元组: ages = (11, 22, 33, 44, 55) 或 ages = tuple((11, 22, 33, 44, 55)) 一般情况下是不需要被人该的数值才使用元 ...
- 【python】求水仙数
for i in range(100, 1000): sum = 0 temp = i while temp: sum = sum + (temp%10) ** 3 temp //= 10 # 注意使 ...
- 【python】aassert 断言
语法 : assert 3>4 结果Traceback (most recent call last): File "<pyshell#0>", line 1, ...
- Python 修饰器
描述:对于函数foo,使用修饰器修饰,在执行foo函数的同时统计执行时间.这样其他函数都可以使用此修饰器得到运行时间. (有返回值和没有返回值的函数要用不同的修饰器似乎) (对于有返回值的函数,不确定 ...
- ASP.NET MVC轻教程 Step By Step 1 ——入门
使用ASP.NET MVC有一段时间了,本人还是非常喜欢ASP.NET MVC这个框架模式的.在经历了WebForm复杂粗暴的做法后,自然感觉简洁优雅的MVC清新可人,只不过WebForm和MVC的设 ...
- QT5.4 计算器程序 打包&发布,解决dll的最新解决方案
QT写界面还是很不错,就是打包会比较麻烦,折腾了一天总算是打包完成了. QT软件的打包发布一个难点是必备dll文件的识别,现在高版本QT自带了一个windeployqt工具,直接会把需要的dll生成一 ...
- [CC150] Find a line passing the most number of points
Problem: Given a two-dimensional graph with points on it, find a line which passes the most number o ...