首先说,上大学这么长时间数学是真的是忘的差不多了,求两个直线的交点竟然让我纠结了好长时间。。。
题的大意是给一个曲折的管子,当光线照入时求可以照的最长的距离!
思路:对于可以照的最长的管子,总是经过管子的上下转折点的,所以可以采用枚举上下转折点来求得光线可以最长到达的距离!
对于每个枚举出来的直线,对于每一个上下转折点,如果上转折点在下方的话就是有交点了,下转折点在直线的上方就也是有交点了,求出交点,找到最大的x就可以了!
分析了别人的代码,那个上面有很多简化的部分,有点看不懂额,所以我就用他的思路但是没有写简化的部分,菜鸟啊啊啊啊啊!
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
typedef struct point
{
double x,y;
}rr;
#define exp 0.000000001
point up[25],down[25];
int n;
double Max;
double judge(point p1,point p2,point p3)
{
return (p3.y-p1.y)*(p2.x-p1.x)-(p2.y-p1.y)*(p3.x-p1.x);
}
void len(point p1,point p2,point p3,point p4)
{
double k=(p1.y-p2.y)/(p1.x-p2.x);
double b=p1.y-p1.x*k;
double k1=(p3.y-p4.y)/(p3.x-p4.x);
double b1=p3.y-k1*p3.x;
double x=(b-b1)/(k1-k);
if(x>Max)
Max=x;
}
int fun(point s,point t)
{
int i,flag=0;
if(judge(s,t,up[0])<-exp || judge(s,t,down[0])>exp)
return 0;
for(i=1; i<=n-1; i++)
{
if(judge(s,t,up[i])<-exp)
{
flag=1;
break;
}
if(judge(s,t,down[i])>exp)
{
flag=2;
break;
}
}
if(i==n)
return 1;
// if(i<j)//在j之前的有个点该光线都不可以通过,那么就直接舍弃了
// return 0;
point p1,p2;
if(flag==1)
{
p1=up[i-1];
p2=up[i];
}
if(flag==2)
{
p1=down[i-1];
p2=down[i];
}
len(s,t,p1,p2);
return 0;
}
int main()
{
int i,j;
while(scanf("%d",&n)&&n)
{
for(i=0; i<n; i++)
{
scanf("%lf%lf",&up[i].x,&up[i].y);
down[i].x=up[i].x;
down[i].y=up[i].y-1;
}
int sign=0;
Max=-10000000;
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
if(fun(up[i],down[j]))//对点进行枚举的
{
sign=1;
break;
}
if(fun(down[i],up[j]))
{
sign=1;
break;
}
}
}
if(sign==1)
printf("Through all the pipe.\n");
else
printf("%0.2lf\n",Max);
}
return 0;
}