线段相交+卡点——poj1039
计算几何里常用的套路:两两枚举点卡住,然后看是不是满足条件
poj上的题依然有很多坑,答案可能是负数,因为这个wa了好久
/* 枚举上端点i,下端点j,作为光线,那么max(i,j)以前的所有管道线段都不可以与该线相交 同时求出max(i,j)以后的最近的交点在哪里(或没有) */ #include<iostream> #include<cstring> #include<cmath> #include<cstdio> using namespace std; #define N 205 typedef double db; const db eps=1e-8; const db pi=acos(-1); int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;} int cmp(db k1,db k2){return sign(k1-k2);} struct point{ db x,y; point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} point operator * (db k1) const{return (point){x*k1,y*k1};} point operator / (db k1) const{return (point){x/k1,y/k1};} }; db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} int intersect(db l1,db r1,db l2,db r2){ if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1; } int checkSSS(point k1,point k2,point k3,point k4){//不严格相交 return sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0; } int checkSS(point k1,point k2,point k3,point k4){//k1,k2:L k3,k4:S return sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<0; } int samedir(point k1,point k2,point k3,point k4){ return sign(cross(k2-k1,k3-k1))*sign(cross(k2-k1,k4-k1))>0; } point getLL(point k1,point k2,point k3,point k4){ db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2); } int n; point up[N],down[N],k1,k2,k3,k4; int main(){ while(cin>>n && n){ for(int i=1;i<=n;i++) { cin>>up[i].x>>up[i].y; down[i]=up[i]; down[i].y--; } double Max=-1e16;//这里一定要负无穷 int flag=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)if(i!=j){ int k;k1=up[i];k2=down[j]; for(k=1;k<n;k++){ if(checkSS(k1,k2,up[k],up[k+1]) || checkSS(k1,k2,down[k],down[k+1])) break; //和边相交 if(!checkSSS(k1,k2,up[k],down[k]) || !checkSSS(k1,k2,up[k+1],down[k+1])) break; //跑到外面 } if(k==n){flag=1;continue;} if(k<max(i,j))continue;//这样的光线不合法 //和段 k,k+1 相交了 if(checkSSS(k1,k2,up[k],up[k+1])){ k3=getLL(k1,k2,up[k],up[k+1]); Max=max(Max,k3.x); } if(checkSSS(k1,k2,down[k],down[k+1])){ k3=getLL(k1,k2,down[k],down[k+1]); Max=max(Max,k3.x); } } if(flag){ puts("Through all the pipe."); continue; } else printf("%.2f\n",Max); } }