POJ3608(旋转卡壳--求两凸包的最近点对距离)
分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696
考虑如下的算法, 算法的输入是两个分别有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.输出最小距离。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h> using namespace std; const int N=50000;
const double eps=1e-9;
const double INF=1e99; struct Point
{
double x,y;
}; Point P[N],Q[N]; double cross(Point A,Point B,Point C)
{
return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
} 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 multi(Point A,Point B,Point C)
{
return (B.x-A.x)*(C.x-A.x)+(B.y-A.y)*(C.y-A.y);
} //顺时针排序
void anticlockwise(Point p[],int n)
{
for(int i=0;i<n-2;i++)
{
double tmp=cross(p[i],p[i+1],p[i+2]);
if(tmp>eps) return;
else if(tmp<-eps)
{
reverse(p,p+n);
return;
}
}
} //计算C点到直线AB的最短距离
double Getdist(Point A,Point B,Point C)
{
if(dist(A,B)<eps) return dist(B,C);
if(multi(A,B,C)<-eps) return dist(A,C);
if(multi(B,A,C)<-eps) return dist(B,C);
return fabs(cross(A,B,C)/dist(A,B));
} //求一条直线的两端点到另外一条直线的距离,反过来一样,共4种情况
double MinDist(Point A,Point B,Point C,Point D)
{
return min(min(Getdist(A,B,C),Getdist(A,B,D)),min(Getdist(C,D,A),Getdist(C,D,B)));
} double Solve(Point P[],Point Q[],int n,int m)
{
int yminP=0,ymaxQ=0;
for(int i=0;i<n;i++)
if(P[i].y<P[yminP].y)
yminP=i;
for(int i=0;i<m;i++)
if(Q[i].y>Q[ymaxQ].y)
ymaxQ=i;
P[n]=P[0];
Q[m]=Q[0];
double tmp,ans=INF;
for(int i=0;i<n;i++)
{
while(tmp=cross(P[yminP+1],Q[ymaxQ+1],P[yminP])-cross(P[yminP+1],Q[ymaxQ],P[yminP])>eps)
ymaxQ=(ymaxQ+1)%m;
if(tmp<-eps) ans=min(ans,Getdist(P[yminP],P[yminP+1],Q[ymaxQ]));
else ans=min(ans,MinDist(P[yminP],P[yminP+1],Q[ymaxQ],Q[ymaxQ+1]));
yminP=(yminP+1)%n;
}
return ans;
} int main()
{
int n,m;
while(cin>>n>>m)
{
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
cin>>P[i].x>>P[i].y;
for(int i=0;i<m;i++)
cin>>Q[i].x>>Q[i].y;
anticlockwise(P,n);
anticlockwise(Q,m);
printf("%.5lf\n",min(Solve(P,Q,n,m),Solve(Q,P,m,n)));
}
return 0;
}
POJ3608(旋转卡壳--求两凸包的最近点对距离)的更多相关文章
- 「POJ-3608」Bridge Across Islands (旋转卡壳--求两凸包距离)
题目链接 POJ-3608 Bridge Across Islands 题意 依次按逆时针方向给出凸包,在两个凸包小岛之间造桥,求最小距离. 题解 旋转卡壳的应用之一:求两凸包的最近距离. 找到凸包 ...
- 旋转卡壳求两个凸包最近距离poj3608
#include <iostream> #include <cmath> #include <vector> #include <string.h> # ...
- POJ 3608 Bridge Across Islands(旋转卡壳,两凸包最短距离)
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7202 Accepted: ...
- poj 3608(旋转卡壳求解两凸包之间的最短距离)
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9768 Accepted: ...
- poj 3608 旋转卡壳求不相交凸包最近距离;
题目链接:http://poj.org/problem?id=3608 #include<cstdio> #include<cstring> #include<cmath ...
- POJ2187 旋转卡壳 求最长直径
给定平面上的一些散点集,求最远两点距离的平方值. 题解: 旋转卡壳求出凸包,然后根据单调性,求出最远两点的最大距离 #pragma GCC optimize(2) #pragma G++ optimi ...
- poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方
旋转卡壳求凸包的直径的平方 板子题 #include<cstdio> #include<vector> #include<cmath> #include<al ...
- POJ 2187 Beauty Contest【旋转卡壳求凸包直径】
链接: http://poj.org/problem?id=2187 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...
- UVa 1453 - Squares 旋转卡壳求凸包直径
旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...
随机推荐
- java.util.LinkedList源码分析
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, D ...
- Xamarin 实现android gridview 多选
参考文章:http://blog.csdn.net/zhouyuanjing/article/details/8372686 GridView初始化代码: gridViewStudent = Find ...
- WF 快速入门
WF(Windows Workflow Foundation ,中文译为:Windows工作流基础)是一种基于更高级抽象概念的编程语言,适合于实现业务流程.虽然可以通过使用图形化的工具(Workflo ...
- php 批量生成html,txt文件的方法(实例代码)
php批量生成html,txt文件的实现代码. 首先,建立一个conn.php 链接数据库. <?php $link = mysql_connect("mysql_host" ...
- 【转】【C#】无边框窗体移动的三种方法
1. 重写WndProc protected override void WndProc(ref Message m) { const int WM_NCHITTEST = 0x84; const i ...
- Nat网络地址转换
Nat中的术语 -------------------------------------------------------------------------------------------- ...
- 对vector等STL标准容器的排序操作
[+] STL提供的Sort 算法 所有sort算法介绍 sort 中的比较函数 sort 的稳定性 全排序 局部排序 nth_element 指定元素排序 partition 和stable_par ...
- 2016 系统设计第一期 (档案一)MVC form数据提交
前几天我发现 MVC 虽然解决了webform的问题但是用起来真的很麻烦,不知道是我刚接触的原因还是为什么,感觉有很多的局限性,对于form的提交一个form只能绑定一个action,代码如下: @u ...
- Unity3d之Socket UDP协议
原文地址:http://blog.csdn.net/dingkun520wy/article/details/49201245 (一)Socket(套接字)UDP协议的特点 1.是基于无连接的协议,没 ...
- 【BZOJ 1010】 [HNOI2008]玩具装箱toy
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...