您的位置:首页 > 其它

POJ 1039 Pipe

2016-01-24 11:01 260 查看
枚举两个点作为光线,计算最远的点即可

可以把管子一段一段分开来看,计算光线是否在每一段管子内,某一段内出界了,那么算交点坐标

注意判断光线不能进入第一个管子

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: