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: ...
随机推荐
- Jquery 实现瀑布流布局
//保证img文件夹下有图片//引入jquery <script src="Script/jquery-1.7.2.js"></script> <st ...
- css3动画使用技巧之—JQ配合css3实现轮播之animation-delay应用
<!DOCTYPE html> <html> <head> <title>css3动画使用技巧之—JQ配合css3实现轮播之animation-dela ...
- js实现幻灯片播放图片示例代码
幻灯片播放图片的效果想必大家都有见到过吧,下面有个不错的示例,感兴趣的朋友可以参考下 复制代码代码如下: <select id="img_date" style=" ...
- Oracle课堂实验一“表的使用”代码。
--创建本地管理表空间CustomerTBSCREATE TABLESPACE CustomerTBS DATAFILE 'd:\Oracle11\product\11.2.0\ora ...
- lua在MacOS系统上的安装方法
lua是一种非常小巧的脚本语言,由标准C编写而成,可以很方便的调用c/c++或者被c/c++.另外相关的还有一个luaJIT,是lua在某些平台上的编译器. 我们在这里只安装lua. 1.检测电脑上是 ...
- 005 Python的数值类型
005 Python的数值类型 BIF 指的是内置函数,一般不作为变量命名.如 input,while,if,else,float,等等.整型:整数.(python3.0版本把整型和长整型结合在 ...
- Visual C++ 6.0常用快捷键
一.常用编译相关的快捷键 1.编译(单个文件) Ctrl+F7 2.连接 F7 3.运行 Ctrl+F5 二.常用调试相关的快捷键 1.GO(全速运行) F5 2.Stop Debuging(停 ...
- linux vi 使用
vi 有一般模式和编辑模式 如vi test.txt 是首先进入的一般模式,一般模式下只能进行复制.删除.粘贴文件数据, 在一般模式下按i .I.a.A.o.O 都能进入编辑模式,按下不同的键进入编辑 ...
- 设计模式之策略模式Strategy
/** * 策略设计模式 * 策略模式:定义一系列的算法族,使他们之间可以相互转换,动态的改变其行为. * 问题:设计一个鸭子模拟游戏. * 现在有一群鸭子: * ①这些鸭可以有飞的行为(分为快和慢) ...
- VC提交网页表单(一共八篇)
VC提交网页表单-自动评论留言(1)http://blog.csdn.net/wangningyu/article/details/4526357VC提交网页表单-自动评论留言(2)http://bl ...