POJ 1039 Pipe
枚举两个点作为光线,计算最远的点即可
可以把管子一段一段分开来看,计算光线是否在每一段管子内,某一段内出界了,那么算交点坐标
注意判断光线不能进入第一个管子
#include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<list> #include<algorithm> using namespace std; const double eps=1e-8; int n; struct Point { double x; double y; } point[100]; struct Line { Point a; Point b; }line[100]; struct X { double a,b,c; }line1,line2; struct Pipe { Line line1;//上面线段 Line line2;//下面线段 double leftX; double rightX; double lineLeftY; double lineRightY; } pipe[100]; Point jiaodian(double a,double b,double c,double d,double e,double f,double g,double h) { double X1=a,Y1=b,X2=c,Y2=d,X3=e,Y3=f,X4=g,Y4=h; line1.a=Y2-Y1; line1.b=X1-X2; line1.c=X2*Y1-X1*Y2; line2.a=Y4-Y3; line2.b=X3-X4; line2.c=X4*Y3-X3*Y4; double ansX=1.0*(line1.b*line2.c-line2.b*line1.c)/(line1.a*line2.b-line2.a*line1.b); double ansY=-1.0*(line2.a*line1.c-line1.a*line2.c)/(line1.a*line2.b-line2.a*line1.b); Point ret; ret.x=ansX; ret.y=ansY; // printf("--- %.2lf %.2lf\n",ansX,ansY); return ret; } int main() { while(~scanf("%d",&n)) { if(!n) break; for(int i=1; i<=n; i++) { scanf("%lf%lf",&point[i].x,&point[i].y); point[i+n].x=point[i].x; point[i+n].y=point[i].y-1; } for(int i=1;i<=n-1;i++) { line[i].a=point[i]; line[i].b=point[i+1]; line[i+n].a=point[i+n]; line[i+n].b=point[i+n+1]; pipe[i].line1=line[i]; pipe[i].line2=line[i+n]; } for(int i=1;i<=n-1;i++) { pipe[i].leftX=pipe[i].line1.a.x; pipe[i].rightX=pipe[i].line1.b.x; } bool Max=0; double ans=-9999999; for(int i=1;i<=2*n;i++) { for(int j=1;j<=2*n;j++) { if(fabs(point[i].x-point[j].x)<=eps) continue; double X1=point[i].x; double Y1=point[i].y; double X2=point[j].x; double Y2=point[j].y; double A = Y2 - Y1; double B = X1 - X2; double C = X2*Y1 - X1*Y2; for(int k=1;k<=n-1;k++) { pipe[k].lineLeftY=(-A*pipe[k].leftX-C)/B; pipe[k].lineRightY=(-A*pipe[k].rightX-C)/B; } bool fail=0; for(int k=1;k<=n-1;k++) { if(pipe[k].lineLeftY+eps>=pipe[k].line2.a.y&&pipe[k].lineLeftY<=pipe[k].line1.a.y+eps &&pipe[k].lineRightY+eps>=pipe[k].line2.b.y&&pipe[k].lineRightY<=pipe[k].line1.b.y+eps) continue; else { fail=1; if(pipe[k].lineRightY<pipe[k].line2.b.y&& pipe[k].lineLeftY+eps>=pipe[k].line2.a.y&&pipe[k].lineLeftY<=pipe[k].line1.a.y+eps)//和下面的相交了 { Point jiaodian1=jiaodian(point[i].x,point[i].y,point[j].x,point[j].y, pipe[k].line2.a.x,pipe[k].line2.a.y,pipe[k].line2.b.x,pipe[k].line2.b.y); ans=max(ans,jiaodian1.x); } else if(pipe[k].lineRightY>pipe[k].line1.b.y &&pipe[k].lineLeftY+eps>=pipe[k].line2.a.y&&pipe[k].lineLeftY<=pipe[k].line1.a.y+eps)//和上面的相交了 { Point jiaodian1=jiaodian(point[i].x,point[i].y,point[j].x,point[j].y, pipe[k].line1.a.x,pipe[k].line1.a.y,pipe[k].line1.b.x,pipe[k].line1.b.y); ans=max(ans,jiaodian1.x); } break; } } if(fail==0) {Max=1; break;} } if(Max) break; } if(Max) printf("Through all the pipe.\n"); else printf("%.2lf\n",ans+eps); } return 0; }