题目:题目链接

题意:给出两个多边形,求这两个多边形的最近距离

分析:旋转卡壳

学习旋转卡壳:

如果多边形相交, 那么最小距离就变得没有意义了。 然而, 这个问题的另一个版本, 凸多边形顶点对间最小距离对

于相交和非相交的情况都有解存在。回到我们的主问题: 直观的, 确定最小距离的点不可能包含在多边形的内部。

与最大距离问题相似, 我们有如下结论:

两个凸多边形 P 和 Q 之间的最小距离由多边形间的对踵点对确立。 存在凸多边形间的三种多边形间的对踵点对, 因

此就有三种可能存在的最小距离模式:“顶点-顶点”的情况 “顶点-边”的情况 “边-边”的情况

换句话说, 确定最小距离的点对不一定必须是顶点。 下面的三个图例表明了以上结论:

    

给定结果, 一个基于旋转卡壳的算法自然而然的产生了:

考虑如下的算法, 算法的输入是两个分别有 m 和 n 个顺时针给定顶点的凸多边形 P 和 Q。 计算 P 上 y 坐标值

最小的顶点(称为 yminP ) 和 Q 上 y 坐标值最大的顶点(称为 ymaxQ)。 为多边形在 yminP 和 ymaxQ 处构造

两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧。 此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和

ymaxQ 成为了多边形间的一个对踵点对。 计算距离(yminP,ymaxQ) 并且将其维护为当前最小值。 顺时针同时旋转平

行线直到其中一个与其所在的多边形的边重合。 如果只有一条线与边重合, 那么只需要计算“顶点-边”对踵点对

和“顶点-顶点”对踵点对距离。 都将他们与当前最小值比较, 如果小于当前最小值则进行替换更新。 如果两条切

线都与边重合, 那么情况就更加复杂了。 如果边“交叠”, 也就是可以构造一条与两条边都相交的公垂线(但是

在顶点处相交), 那么就计算“边-边”距离。 否则计算三个新的“顶点-顶点”对踵点对距离。 所有的这些距离

都与当前最小值进行比较, 若小于当前最小值则更新替换。 
重复执行步骤。直到新的点对为(yminP,ymaxQ)。

输出最大距离。

旋转卡壳模式保证了所有的对踵点对(和所有可能的子情况)都被考虑到。 此外, 整个算法拥有现行的时间复杂

度, 因为(除了初始化), 只有与顶点数同数量级的操作步数需要执行。

最小距离和最大距离的问题表明了旋转卡壳模型可以用在不同的条件下(与先前的直径和宽度问题比较)。 这个模

型可以应用于两个多边形的问题中。

“最小盒子”问题(最小面积外接矩形)通过同一多边形上两个正交切线集合展示了另一种条件下旋转卡壳的应用。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 10015
#define PR 1e-8
struct TPoint
{double x,y;TPoint(){};TPoint(double _x,double _y):x(_x),y(_y){}TPoint operator-(const TPoint p){return TPoint(x-p.x,y-p.y);}
}s;
struct TPolygon
{int n;TPoint p[N];
}ply1,ply2;
int dblcmp(double a) {return fabs(a)<PR?0:a>0?1:-1;}
double MIN(double a,double b) {return a<b?a:b;}
double dist(TPoint a,TPoint b)//两点距
{TPoint c(a-b);return sqrt(c.x*c.x+c.y*c.y);
}
double cross(TPoint a,TPoint b,TPoint c)//叉积
{TPoint s(b-a),t(c-a);return s.x*t.y-s.y*t.x;
}
bool cmop(TPoint a,TPoint b)//x、y排序
{if(fabs(a.x-b.x)<PR) return a.y<b.y;else return a.x<b.y;
}
bool cmp(TPoint a,TPoint b)//叉积内排序
{int d1=dblcmp(cross(s,a,b));return d1>0||(d1==0&&dist(s,a)<dist(s,b));
}
TPolygon graham(TPolygon ply)//凸包
{int i,j,k;sort(ply.p,ply.p+ply.n,cmop);s=ply.p[0]; k=2;sort(ply.p+1,ply.p+ply.n,cmp);for(i=2,k=2;i<ply.n;i++){while(k>1&&(dblcmp(cross(ply.p[k-2],ply.p[i],ply.p[k-1])))>=0) k--;ply.p[k++]=ply.p[i];}ply.n=k;return ply;
}
double disps(TPoint a,TPoint b,TPoint c)//点到线段的最近距离
{TPoint s(a-b),t(c-b);if(s.x*t.x+s.y*t.y<0) return dist(a,b);s=(a-c); t=(b-c);if(s.x*t.x+s.y*t.y<0) return dist(a,c);return fabs(cross(a,b,c))/(dist(b,c));
}
double disss(TPoint a,TPoint b,TPoint c,TPoint d)//两条线段最近距离
{return MIN(MIN(disps(a,c,d),disps(b,c,d)),MIN(disps(c,a,b),disps(d,a,b)));
}
double solve(TPolygon pl,TPolygon pr,int p,int q)//旋转卡壳,求凸边形最近距离
{int i;double tmp,min=1e90;pl.p[pl.n]=pl.p[0]; pr.p[pr.n]=pr.p[0];for(i=0;i<pl.n;i++){while((tmp=cross(pl.p[p+1],pr.p[q+1],pl.p[p])-cross(pl.p[p+1],pr.p[q],pl.p[p]))>PR)q=(q+1)%pr.n;if(tmp<-PR) min=MIN(min,disps(pr.p[q],pl.p[p],pl.p[p+1]));else min=MIN(min,disss(pl.p[p],pl.p[p+1],pr.p[q],pr.p[q+1]));p=(p+1)%pl.n;}return min;
}
void gettop(TPolygon pl,TPolygon pr,int &l,int &r)//得到最下和最上点
{int i;l=r=0;for(i=0;i<pl.n;i++){if((dblcmp(pl.p[i].y-pl.p[l].y))<0) l=i;}for(i=0;i<pr.n;i++){if((dblcmp(pr.p[i].y-pr.p[r].y))>0) r=i;}
}
int main()
{while(scanf("%d%d",&ply1.n,&ply2.n),ply1.n&&ply2.n){int i,l,r;for(i=0;i<ply1.n;i++) scanf("%lf%lf",&ply1.p[i].x,&ply1.p[i].y);for(i=0;i<ply2.n;i++) scanf("%lf%lf",&ply2.p[i].x,&ply2.p[i].y);ply1=graham(ply1);ply2=graham(ply2);gettop(ply1,ply2,l,r);double mindis=MIN(solve(ply1,ply2,l,r),solve(ply2,ply1,r,l));//最近距离printf("%.5lf\n",mindis);}return 0;
}

POJ3608-旋转卡壳相关推荐

  1. POJ3608(旋转卡壳--求两凸包的最近点对距离)

    题目:Bridge Across Islands 分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696 考虑如下的算法, 算法的 ...

  2. 算法复习——凸包加旋转卡壳(poj2187)

    题目: Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest ...

  3. Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

    \(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...

  4. BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]

    1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1435  Solv ...

  5. 算法学习:计算几何旋转卡壳

    [定义] [对踵点]多边形上存在平行切线的两点 [多边形半径]多边形上任意两点的最大长度 [旋转卡壳] 选取y轴上,最高和最低的两个点,令两条平行于x轴的线切过这两点 然后我们开始让这两条线旋转 当一 ...

  6. bzoj 1069 [SCOI2007]最大土地面积——旋转卡壳

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1069 发现 n 可以 n^2 .所以枚举对角线,分开的两部分三角形就可以旋转卡壳了. 注意坐 ...

  7. 【BZOJ1185】【HNOI2007】最小矩形覆盖(凸包+旋转卡壳)

    传送门 题意:求最小矩阵覆盖 有这样一个结论:矩阵一定有一条边在凸包上(不会证) 那可以枚举每条边 同时旋转卡壳 只是这时不只维护一个对踵点对,同时在左右侧再维护一个最远点 可以发现左右最远点一定是和 ...

  8. poj 2079(旋转卡壳)

    题意:求出平面内的点集所组成的面积最大的三角形. 解题思路:考虑凸包+旋转卡壳.面积最大的三角形的三点必定在凸包的顶点上,只不过这里要注意,三角形的边不一定就是凸包的边,有可能三角形相邻两点是横跨凸包 ...

  9. poj 2187 Beauty Contest (凸包: 最远点对,最长直径 , 旋转卡壳法)

    http://poj.org/problem?id=2187 题意: 最长的点对近距离的平方: 题解: 旋转卡壳法, 要注意的地方是,有 所有点共线的情况,所以,(求凸包时)要将,共线点去出 :    ...

  10. POJ 2187 凸包+旋转卡壳

    思路: 求个凸包 旋转卡壳一下 就求出来最远点对了 注意共线情况 也就是说   凸包如果有一堆点共线保留端点即可 //By SiriusRen #include <cmath> #incl ...

最新文章

  1. 在HYPER-V中利用差异磁盘和SYSPREP技术安装多个WINDOWS 2008
  2. rabbitmq 消息队列 多重绑定
  3. 如何判断当前主机是物理机还是虚拟机
  4. Android4.3 屏蔽HOME按键返回桌面详解(源码环境下)
  5. 详解:Linux Chrony 设置服务器集群同步时间
  6. Lombok常用注解和功能
  7. 联想T460 Win10下“系统中断”CPU占用率高的解决办法
  8. 在Ubuntu上安装misterhouse
  9. UITableViewCell不重用代码
  10. dynamic集合动态添加属性
  11. 使用一个运放滤三次谐波 二阶有源带通滤波器的电路设计及波形效果
  12. 牛客小白月赛17 - J - 计数(组合数学隔板法)
  13. subtype,supertype 与 subclass,superclass 的异同
  14. 奥沙利文独家授权数字藏品正式发售 线上线下搭配多款专属福利
  15. 【Linux学习笔记】38:有关Linux进程家族树
  16. ffmpeg播放器声音效果2-变速不变调及变调
  17. Git 学习之团队协作(Gitee实操)
  18. mysql 数字 除以 一万_腾讯股票接口、和讯网股票接口、新浪股票接口、雪球股票数据、网易股票数据...
  19. hihoCoder #1135 : Magic Box
  20. 渗透测试团队协作平台——Dradis Pro

热门文章

  1. 面对这样的网络状况我真的醉了
  2. 暖火柴打一数字_火柴里的天堂
  3. 关于setTimeout多次点击会多次执行方法导致运行速度加快的问题
  4. LeetCode(中等)买卖股票的最佳时机含手续费(c#)
  5. rono在oracle的作用_Oracle中存储过程的作用和用法
  6. 25分钟破亿 首销火爆的moto edge X30给友商们出了个难题
  7. 精益生产排程系统(APS)优化的力量是什么?
  8. 香港深水埗将办新春美食节 助青年一尝创业滋味
  9. 使用Python+OpenCV+FaceNet 实现亚马逊门铃系统上的人脸识别
  10. Android类似微信详细地址选择(高德地图)