线段与直线相交时,端点重合情况需要考虑, 所以是不规范相交。
枚举时注意逻辑,不重不漏。
模版运用需要灵活.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define maxn 20+5
const double eps=1e-8;
int sgn(double x)
{
if(fabs(x)==0)
return 0;
if(x<0)
return -1;
else
return 1;
}
int Max(int a,int b)
{
return a>b?a:b;
}
struct point
{
double x,y;
point() {}
point(double _x,double _y)
{
x=_x;
y=_y;
}
};
typedef point vector;
vector operator - (point A,point B)
{
return point(A.x-B.x,A.y-B.y);
}
double operator ^ (vector A,vector B)
{
return A.x*B.y-A.y*B.x;
}
struct line
{
point p,q;
};
double crosspoint(line l1,line l2) //直线相交求交点
{
double a1=(l1.q-l1.p)^(l2.p-l1.p);
double a2=(l1.q-l1.p)^(l2.q-l1.p);
return ((l2.p.x*a2-l2.q.x*a1)/(a2-a1));
}
int linecrossseg(line l1,line l2) //2 规范相交 1 非规范相交 0 不相交 ,l1是直线,l2是线段
{
int d1=sgn((l1.q-l1.p)^(l2.q-l1.p));
int d2=sgn((l1.q-l1.p)^(l2.p-l1.p));
if((d1^d2)==-2)
return 2;
return (d1==0)||(d2==0);
}
point up[maxn];
point down[maxn];
using namespace std;
int main()
{
//freopen("input.txt","r",stdin);
bool flag;
line l,light,l1,l2;
int n;
double x,y,max;
while(scanf("%d",&n) && n!=0)
{
flag=true;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&x,&y);
up[i]=point(x,y);
down[i]=point(x,y-1);
}
max=up[1].x;
//cout<<max<<endl;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int k,k0;
if(i!=j)
{
light.p=up[i];
light.q=down[j];
for(k=1;k<=n;k++)
{
l.p=up[k];
l.q=down[k];
if(linecrossseg(light,l)==0)
{
k0=k;
break;
}
}
if(k==n+1)
flag=false;
else
{
if(k0>Max(i,j))
{
//printf("%d %d %d\n",i,j,k0);
double tmp;
l1.p=up[k0-1];
l1.q=up[k0];
if(linecrossseg(light,l1)!=0)
{
tmp=crosspoint(light,l1);
if(tmp>max)
max=tmp;
}
l2.p=down[k0-1];
l2.q=down[k0];
if(linecrossseg(light,l2)!=0)
{
tmp=crosspoint(light,l2);
if(tmp>max)
max=tmp;
}
//cout<<max<<endl;
}
}
}
}
if(flag)
printf("%.2f\n",max);
else
cout<<"Through all the pipe.\n";
}
}