题意:已知电缆是由一段段直的管道连接而成的,并知道这些管道的位置,问一束光从最左边射进来,你可以调节光入射的位置和角度,问最远能射到多远。(光束不能射穿管道)
思路:计算几何。从结果反过来可以证:如果一根光线没有擦到2个顶点,那肯定不是最优的解(可以移动或旋转取到一个更优解)。枚举上下两个顶点成光线所在直线,然后判断光线是否能合法,合法的话求出它射到的最远距离。
#include<stdio.h>
#include<math.h>
#define N 25
#define INF 99999999
#define eps 1e-9
struct Point
{
double x,y;
};
Point up[N],down[N];
int n;
int max(int x,int y)
{
if(x>y)return x;
return y;
}
double cross(Point a,Point b,Point c ) //qiu cha ji
{
return ((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
}
int cross_straight_ans_segment(Point a,Point b,Point c,Point d)
{
if(cross(a,b,c)*cross(a,b,d)<=0)
return 1; //xiang jiao
return 0;
}
int bd1_cmp(double d)
{
if(fabs(d)<eps)
return 0;
return d>0?1:-1;
}
int segcross(Point a,Point b,Point c,Point d,Point &p)
{
double s1,s2;
int d1,d2;
s1=cross(a,b,c);
s2=cross(a,b,d);
d1=bd1_cmp(s1);
d2=bd1_cmp(s2);
if((d1^d2)==-2) //求交点坐标
{
p.x=(c.x*s2-d.x*s1)/(s2-s1) ;
return 1;
}
if(d2==0)
{
p.x=d.x;
return 1;
}
if(d1==0)
{
p.x=c.x;
return 1;
}
return 0;
}
void work()
{
int i,j,k;
Point p;
bool all=false;
double ans=-INF;
for(i=0;i<n && !all;i++)
for(j=0;j<n;j++)
{
//if(i==j) continue;
for(k=0;k<n;k++)
if(cross_straight_ans_segment(up[i],down[j],up[k],down[k])==0)
break;
if(k>=n)
{
all=true;
break;
}
if(k>max(i,j))
{
segcross(up[i],down[j],up[k],up[k-1],p);
if(p.x>ans)
ans=p.x;
segcross(up[i],down[j],down[k],down[k-1],p);
if(p.x>ans)
ans=p.x;
}
}
if(all)
printf("Through all the pipe.\n");
else
printf("%.2lf\n",ans);
}
int main()
{
int i;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
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.0;
}
work();
}
return 0;
}
poj 1039
最新推荐文章于 2022-06-27 17:42:24 发布