poj 1039

题意:已知电缆是由一段段直的管道连接而成的,并知道这些管道的位置,问一束光从最左边射进来,你可以调节光入射的位置和角度,问最远能射到多远。(光束不能射穿管道)
思路:计算几何。从结果反过来可以证:如果一根光线没有擦到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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值