poj 3608 Bridge Across Islands题解(凸包+求两凸包间的最近点对)
来源:互联网 发布:淘宝衣服怎么拍照技巧 编辑:程序博客网 时间:2024/04/27 16:07
http://poj.org/problem?id=3608
#include<iostream>#include<fstream>#include<iomanip>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#include<set>#include<map>#include<queue>#include<stack>#include<string>#include<vector>#include<sstream>#include<ctime>#include<cassert>#define LL long long#define eps 1e-8#define inf 999999.0#define zero(a) abs(a)<eps#define N 20#define pi acos(-1.0)using namespace std;struct Point{ double x,y;}p[10005],q[10005],pos;vector<Point >s1,s2;double dist(Point p1,Point p2){ return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}double xmul(Point p0,Point p1,Point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}//Graham_scan求凸包逆时针排序顶点bool cmp(Point p1,Point p2){ if(xmul(pos,p1,p2)>eps) return true; else if(zero(xmul(pos,p1,p2))&&dist(pos,p1)<dist(pos,p2)) return true; return false;}void Graham_scan(vector<Point>&s,Point p[],int n){ for(int i=1;i<n;i++) if(p[i].y<p[0].y||(zero(p[i].y - p[0].y)&&p[i].x<p[0].x)) swap(p[i],p[0]); pos=p[0]; sort(p+1,p+n,cmp); s.clear(); s.push_back(p[0]);s.push_back(p[1]); int i; for(i=2;i<n;i++){//求上凸壳 while(s.size()>1&&xmul(s[s.size()-2],s[s.size()-1],p[i])<eps){//这样构造的凸包是逆时针的。 s.pop_back(); } s.push_back(p[i]); } int tmp=s.size(); s.push_back(p[n-2]); for(i=n-3;i>=0;i--){//求下凸壳 while(s.size()>tmp&&xmul(s[s.size()-2],s[s.size()-1],p[i])<eps){ s.pop_back(); } s.push_back(p[i]); }}//得到向量a1b1和a2b2的位置关系double Get_angle(Point a1,Point b1,Point a2,Point b2){ Point t; t.x=a2.x-(b2.x-a1.x); t.y=a2.y-(b2.y-a1.y); return xmul(a1,b1,t);}double Dist_Point_Seg(Point p,Point a,Point b){ Point t=p; t.x+=a.y-b.y;t.y+=b.x-a.x; if(xmul(a,t,p)*xmul(b,t,p)>eps) return dist(p,a)+eps<dist(p,b)?dist(p,a):dist(p,b); else return fabs(xmul(p,a,b))/dist(a,b);}double Min_Dist_Two_Polygons(vector<Point>s1,vector<Point>s2){ int na=s1.size()-1,nb=s2.size()-1; int lp=0,lq=0; for(int i=1;i<na;i++) if(s1[i].y<s1[lp].y||(zero(s1[i].y-s1[lp].y)&&s1[i].x<s1[lp].x)) lp=i; for(int i=1;i<nb;i++) if(s2[i].y>s2[lq].y||(zero(s2[i].y-s2[lq].y)&&s2[i].x>s2[lq].x)) lq=i; double ans=dist(s1[lp],s2[lq]); int tp=lp,tq=lq; do{ double angle=Get_angle(s1[tp],s1[tp+1],s2[tq],s2[tq+1]); //和两个凸包的边都重合 if(zero(angle)){ ans=min(ans,Dist_Point_Seg(s1[tp],s2[tq],s2[tq+1])); ans=min(ans,Dist_Point_Seg(s1[tp+1],s2[tq],s2[tq+1])); ans=min(ans,Dist_Point_Seg(s2[tq],s1[tp],s1[tp+1])); ans=min(ans,Dist_Point_Seg(s2[tq+1],s1[tp],s1[tp+1])); tp=(tp+1)%na;tq=(tq+1)%nb; } else{ //和第二个凸包的边重合 if(angle<-eps){ ans=min(ans,Dist_Point_Seg(s1[tp],s2[tq],s2[tq+1])); tq=(tq+1)%nb; } //和第一个凸包的边重合 else{ ans=min(ans,Dist_Point_Seg(s2[tq],s1[tp],s1[tp+1])); tp=(tp+1)%na; } } }while(!(lp==tp&&lq==tq)); return ans;}int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF&&n+m){ for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); Graham_scan(s1,p,n); for(int i=0;i<m;i++) scanf("%lf%lf",&q[i].x,&q[i].y); Graham_scan(s2,q,m); printf("%.5f\n",Min_Dist_Two_Polygons(s1,s2)); } return 0;}
0 0
- poj 3608 Bridge Across Islands题解(凸包+求两凸包间的最近点对)
- poj 3608 Bridge Across Islands(卡壳旋转求两个多边形的最近点对)
- POJ 3608 Bridge Across Islands(求两凸包间的最小距离)
- poj 3608 Bridge Across Islands 旋转卡壳(两个凸包的最近距离)
- POJ 3608 Bridge Across Islands(两个凸包最近距离,旋转卡壳)
- POJ 3608 Bridge Across Islands (凸包+旋转卡壳)
- poj 3608 Bridge Across Islands(两个凸包的最短距离)
- POJ 3608 Bridge Across Islands(旋转卡壳 求不相交凸包之间的最短距离)
- poj 3608 Bridge Across Islands
- 【POJ 3608】Bridge Across Islands
- POJ 3608 Bridge Across Islands
- POJ 3608 Bridge Across Islands
- poj 3608 Bridge Across Islands(两凸包最近距离)
- poj 3608 Bridge Across Islands(旋转卡壳求俩凸包间最小间距)
- Bridge Across Islands POJ
- PKU 3608 Bridge Across Islands 凸包+旋转卡壳
- poj 3608 Bridge Across Islands 凸包最短距离
- POJ 3608 Bridge Across Islands(旋转卡壳)
- lamda表达式
- class批量反编译
- poj1077-不作此题人生不完整~经典搜索题
- 浅析ORACLE ERP系统维护方法
- 实战:oracle巡检脚本v1
- poj 3608 Bridge Across Islands题解(凸包+求两凸包间的最近点对)
- spring依赖注入方式及其优缺点
- java垃圾收集器
- Android中的JSON详细总结
- Java的poi技术读取和导入Excel
- 公司法定搞好宏观
- Hibernate的使用
- Objective-C中的Literals
- C语言数组