WA了好多次
说一下错误
第一个地方是旋转卡壳是要进行两次的
第二个地方其实也不算错误,应该是程序运行的精度问题
在下面这部分程序中
//while((tmp=(p[(miny+1)%n]-p[miny])^(p[maxy]-p[(maxy+1)%m]))<-eps) maxy=(maxy+1)%m;//只要在向量miny-miny+1右侧则说明在向对踵点对的方向靠 while((tmp=Get_angle(p[miny],p[miny+1],q[maxy],q[maxy+1]))<-eps) maxy=(maxy+1)%m;
可能在同一个语句中不能进行太多的运算,要不然有可能会导致精度降低
总结就是以后在同一个语句中不要进行过多的运算,要分部分赋值
//最近点对和最远点对产生在有向平行切线上,将一条边平行过去,然后判断 #include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include<algorithm> using namespace std; const double eps=1e-8; struct Point { double x,y; Point (){} Point (double xx,double yy) {x=xx;y=yy;} Point operator -(const Point b)const {return Point(x-b.x,y-b.y);} double operator ^(const Point b)const {return x*b.y-y*b.x;} double operator *(const Point &b)const{ return x*b.x + y*b.y; } }; struct Line { Point s,e; double angle; Line(){} Line(Point ss,Point ee) {s=ss;e=ee;} }; Point p[10005],q[10005],list[10005]; int n,m,top,miny,maxy; double dist(Point a,Point b) { return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y)); } //求点到线段距离,不是点到直线距离 double pointtoseg(Point P,Point b,Point c){ /*Line s=Line(b,c); Point mid; double t=(p-s.s)*(s.e-s.s)/((s.e-s.s)*(s.e-s.s));//s.s到垂点的距离/s.s到s.e的距离 double ans; if(t>=0 && t<=1) { mid.x=s.s.x+(s.e.x-s.s.x)*t; mid.y=s.s.y+(s.e.y-s.s.y)*t; ans=dist(p,mid); } else { if(dist(p,s.s)<dist(p,s.e)) ans=dist(p,s.s); else ans=dist(p,s.e); } printf("%lf\n",ans); return ans;*/ Point result; Line L=Line(b,c); double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); if(t >=0 && t <= 1) { result.x = L.s.x + (L.e.x - L.s.x)*t; result.y = L.s.y + (L.e.y - L.s.y)*t; } else { if(dist(P,L.s) < dist(P,L.e)) result = L.s; else result = L.e; } return dist(result,P); } double segtoseg(Point a,Point b,Point c,Point d){ double ans1=min(pointtoseg(a,c,d),pointtoseg(b,c,d)); double ans2=min(pointtoseg(c,a,b),pointtoseg(d,a,b)); return min(ans1,ans2); } int cmp(Point a,Point b) {//逆时针 double tmp=(a-list[0])^(b-list[0]); if(tmp == 0) return dist(a,list[0]) - dist(b,list[0]) <-eps; else return tmp>0; } void Graham(Point* p,Point* stack,int n){ int k=0; for(int i=0;i<n;i++){ if(p[i].y<p[k].y || (p[i].y==p[k].y && p[i].x<p[k].x)) k=i; } swap(p[0],p[k]); sort(p+1,p+n,cmp); if(n<=2){ for(int i=0;i<n;i++) stack[i]=p[i]; top=n; return; } stack[0]=p[0]; stack[1]=p[1]; top=2; for(int i=2;i<n;i++){ while(top>=2 && ((stack[top-1]-stack[top-2])^(p[i]-stack[top-2]))<eps) top--; stack[top++]=p[i]; } } double Get_angle(Point a1,Point a2,Point b1,Point b2) { return (a2-a1)^(b1-b2); } double rotating(Point* p,int n,Point* q,int m){ miny=0,maxy=0; for(int i=0;i<n;i++) { if(p[i].y<p[miny].y) miny=i; } for(int i=0;i<m;i++) { if(q[i].y>q[maxy].y) maxy=i; } double ans=dist(p[miny],q[maxy]); for(int i=0;i<n;i++){ double tmp; //while((tmp=(p[(miny+1)%n]-p[miny])^(p[maxy]-p[(maxy+1)%m]))<-eps) maxy=(maxy+1)%m;//只要在向量miny-miny+1右侧则说明在向对踵点对的方向靠 while((tmp=Get_angle(p[miny],p[miny+1],q[maxy],q[maxy+1]))<-eps) maxy=(maxy+1)%m; if(fabs(tmp)<eps) ans=min(ans,segtoseg(p[miny],p[(miny+1)%n],q[maxy],q[(maxy+1)%m])); else ans=min(ans,pointtoseg(q[maxy],p[miny],p[(miny+1)%n])); miny=(miny+1)%n; } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE while(scanf("%d%d",&n,&m)) { if(n==0 && m==0) break; //顺时针排列的点 miny=0,maxy=0; for(int i=0;i<n;i++) { scanf("%lf%lf",&list[i].x,&list[i].y); } Graham(list,p,n); n=top; for(int i=0;i<m;i++) { scanf("%lf%lf",&list[i].x,&list[i].y); } Graham(list,q,m); m=top; p[n]=p[0]; q[m]=q[0]; printf("%.5f\n",min(rotating(p,n,q,m),rotating(q,m,p,n))); } return 0; }
POJ 3608 Bridge Across Islands
原文地址:http://blog.csdn.net/lj94093/article/details/44117407