这题并不难,但我却弄了一天。
只要枚举每个上面的点与下面的点的连线,在看这条线能到达的最远的地方。
然后如果这条线与上面或下面的第i条斜线线相交的话,必然会相交与up[i]-down[i]这条垂线相交。
这题找错找了很久,找了各种各样的错。最后还是看了别人的代码才发现算法上出现了问题。
所以以后找错一定要想算法是否错了。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define MAXN 100
#define ESP 1e-8
#define MAXNUM 1e8
struct point
{
double x,y;
point(double _x=0,double _y=0) : x(_x),y(_y) {};
void input() { scanf("%lf%lf",&x,&y); }
};
double sgn(double d)
{ return d > ESP ? 1 : (d < -ESP ? -1 : 0);
}
point operator-(const point &p1,const point &p2)
{ return point(p1.x - p2.x, p1.y - p2.y);
}
double operator*(const point &p1,const point &p2)
{ return p1.x*p2.y - p2.x*p1.y;
}
double operator==(const point &p1,const point &p2)
{
return sgn(p1.x-p2.x)==0 && sgn(p1.y-p2.y)==0;
}
double min(double a,double b) { if(a<b) return a; else return b; }
double max(double a,double b) { if(a>b) return a; else return b; }
int n;
point up[MAXN],down[MAXN];
void init()
{
int i,j,k,r,w;
for(i=1;i<=n;i++)
{
up[i].input();
down[i].x = up[i].x;
down[i].y = up[i].y-1;
}
}
bool jiaodian(point a,point b,point c,point d,point &e)
{
double d1 = (b-a) * (c-a), d2 = (b-a) * (d-a),
d3 = (d-c) * (a-c), d4 = (d-c) * (b-c);
if(sgn(d1)*sgn(d2) > 0)
return false;
e = point( (c.x*d2 - d.x*d1) / (d2-d1) ,
(c.y*d2 - d.y*d1) / (d2-d1) );
return true;
}
double fun(point a,point b)
{
int i,j;
point c,p1,p2;
double k,r,w,x1,x2;
x1 = x2 = MAXNUM;
for(i=1;i<=n;i++)
if( !jiaodian(a,b,up[i],down[i],c) )
{
if(i == 1) return up[1].x;
jiaodian(a,b,up[i],up[i-1],c);
x1 = c.x;
jiaodian(a,b,down[i],down[i-1],c);
x2 = c.x;
return max(x1,x2);
}
// printf("\n");
return up[n].x;
}
void solve()
{
int i,j,k,r,w;
point a;
double ans=-1e8;
ans = up[1].x;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i != j)
{
ans = max(ans, fun(up[i],down[j]) );
// printf("%d %d %f\n",i,j,fun(up[i],down[j]));
}
if(sgn(ans-up[n].x) < 0) printf("%.2f\n",ans);
else printf("Through all the pipe.\n");
}
int main()
{
//freopen("p303.in","r",stdin);
while(scanf("%d",&n) != EOF && n)
{
init();
solve();
}
return 0;
}