POJ 3608 Bridge Across Islands(旋转卡壳求凸多边形最短距离)
2016-01-23 21:49
471 查看
http://poj.org/problem?id=3608
大意:求解两个凸多边形的最短距离。
![](https://img-blog.csdn.net/20160123213918236?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
分析:依然是旋转卡壳来解决。用一对平行支撑线围绕两个凸多边形来寻找最短的距离。
计算P多边形y最小的端点和Q多边形y最大的端点,即ymin,ymax
通过ymin,ymax构造两条支撑射线LP和LQ,方向相反。两个ymin,ymax的端点的距离作为所求距离的初始值,然后旋转两条支撑线。
当满足有一条平行支撑线和凸多边形的边平行(重合)时,开始相应的判断。
判断的情况:
当有一条平行支撑线和凸多边形的边重合:
(1) 点和线段e的距离最短
(2) 点和新点的距离最短(旧点之前已经判断了)
![](https://img-blog.csdn.net/20160123213945924?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20160123214003502?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
当两条平行线均和凸多边形的边重合时:
(3) 线段和线段的距离是最短的(一段距离)
(4) 最短距离产生于线段的端点的距离(四段距离)
![](https://img-blog.csdn.net/20160123214038075?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20160123214058425?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
上面的求解情况转化成 点到点的距离,点到线的距离,线到线的距离(可转化成点到线的距离)
![](https://img-blog.csdn.net/20160123214805013?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
大意:求解两个凸多边形的最短距离。
分析:依然是旋转卡壳来解决。用一对平行支撑线围绕两个凸多边形来寻找最短的距离。
计算P多边形y最小的端点和Q多边形y最大的端点,即ymin,ymax
通过ymin,ymax构造两条支撑射线LP和LQ,方向相反。两个ymin,ymax的端点的距离作为所求距离的初始值,然后旋转两条支撑线。
当满足有一条平行支撑线和凸多边形的边平行(重合)时,开始相应的判断。
判断的情况:
当有一条平行支撑线和凸多边形的边重合:
(1) 点和线段e的距离最短
(2) 点和新点的距离最短(旧点之前已经判断了)
当两条平行线均和凸多边形的边重合时:
(3) 线段和线段的距离是最短的(一段距离)
(4) 最短距离产生于线段的端点的距离(四段距离)
上面的求解情况转化成 点到点的距离,点到线的距离,线到线的距离(可转化成点到线的距离)
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const double eps=1e-7,inf=1e99; const int N=1e4+10; struct point{ double x,y; }; double dis(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double cross(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } double multi(point p0,point p1,point p2){ //点积 p0为角点 return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y); } double getDis(point p0,point p1,point p2){ if(dis(p0,p1)<eps) return dis(p2,p0); if(multi(p0,p1,p2)<-eps) return dis(p2,p0); if(multi(p1,p0,p2)<-eps) return dis(p2,p1); return fabs(cross(p0,p1,p2)/dis(p0,p1)); //点到线的距离 } double minDis(point p1,point p2,point p3,point p4){ return min(min(getDis(p1,p2,p3),getDis(p1,p2,p4)),min(getDis(p3,p4,p1),getDis(p3,p4,p2))); } double work(point p[],point q[],int top1,int top2){ int ymin=0,ymax=0; for(int i=0;i<top1;i++){ if(p[i].y<p[ymin].y) ymin=i; } for(int i=0;i<top2;i++){ if(q[i].y>q[ymax].y) ymax=i; } p[top1]=p[0]; q[top2]=q[0]; double t,ans=inf; for(int i=0;i<top1;i++){ while(t=cross(p[ymin],p[ymin+1],q[ymax])-cross(p[ymin],p[ymin+1],q[ymax+1])<-eps) ymax=(ymax+1)%top2; if(t>eps) ans=min(ans,getDis(p[ymin],p[ymin+1],q[ymax])); else ans=min(ans,minDis(p[ymin],p[ymin+1],q[ymax],q[ymax+1])); ymin=(ymin+1)%top1; } return ans; } point p ,q ; int top1,top2; int main() { //freopen("cin.txt","r",stdin); while(cin>>top1>>top2&&(top1+top2)){ for(int i=0;i<top1;i++){ scanf("%lf%lf",&p[i].x,&p[i].y); }; for(int i=0;i<top2;i++){ scanf("%lf%lf",&q[i].x,&q[i].y); } printf("%.5lf\n",min(work(p,q,top1,top2),work(q,p,top2,top1))); } return 0; }
相关文章推荐
- JS操作JSON总结
- weblogic的nohup.out日志的管理
- css
- 桶排序
- 【原】mysql慢日志分析
- 数据库——环境初建改端口和密码(转)
- 斯坦福机器学习在线demo
- PAT 1054
- eclipse 常用快捷键最佳实践
- PAT 1055. The World's Richest
- LeetCode Best Time to Buy and Sell Stock II(贪心)
- 《Python for kids》学习笔记(四)
- vim
- Linux CentOS 7.0 下 rar unrar的安装
- 【Unity Shader】概述以及Diffuse shader和unity5新功能Standard shader
- SQL SERVER: 合并相关操作(Union,Except,Intersect) - 转载
- Hive on Spark:起点
- Android使用DrawerLayout和ToolBar实现仿知乎侧滑菜单
- JQuery DataTables
- cuda语法高亮设置