poj 1039 Pipe(叉乘。。。)

时间:2023-03-09 06:03:34
poj 1039 Pipe(叉乘。。。)

题目:http://poj.org/problem?id=1039

题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道.

思路:最优的是 光线过一个上顶点,一个下顶点。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
using namespace std;
const double eps=1e-;
const int INF=<<;
int n; struct point
{
double x,y;
}up[],down[]; int dblcmp(double x)
{
if(x<-eps) return -;//一定要注意精度问题,不然样例都过不了
if(x>eps) return ;
return ; //在这里把接近0的数值都看成了0,实际这些数值就是0
} double det(double x1,double y1,double x2,double y2)// 向量坐标点的叉乘
{
return x1*y2-x2*y1;
}
double cross(point a,point b,point c)//ab和ac向量的叉乘
{
return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
} double getx(point a,point b,point c,point d)//求ab和cd组成的直线交点的横坐标。
{
double b1,b2,k1,k2;
k1=(b.y-a.y)/(b.x-a.x);
k2=(d.y-c.y)/(d.x-c.x);
b1=a.y-k1*a.x;
b2=c.y-k2*c.x;
return (b2-b1)/(k1-k2);
}
void solve()
{
int i,j,k;
double ans=-INF,cnt;
for(i=; i<n; i++)
{
for(j=; j<n; j++)
{
if(i==j) continue; //同一个横坐标的跳过
for(k=; k<n; k++)
{
if(dblcmp(cross(up[i],down[j],up[k]))*dblcmp(cross(up[i],down[j],down[k]))>)
break;//叉乘大于0说明 这条直线在两个点的同一侧,从叉乘的定义可以看出|a||b|sin&;
}
if(k<max(i,j)) continue; //如果这样的话 说明光线不存在。。。
cnt=getx(up[i],down[j],up[k],up[k-]);//找上顶点线的交点
if(cnt>ans) ans=cnt;
cnt=getx(up[i],down[j],down[k],down[k-]);//找下顶点线的交点
if(cnt>ans) ans=cnt;
if(k==n)
{
cout<<"Through all the pipe."<<endl;
return;
}
}
}
cout<<fixed<<setprecision()<<ans<<endl;
}
int main()
{
int i;
while(~scanf("%d",&n)&&n)
{
for(i=; i<n; i++)
{
cin>>up[i].x; cin>>up[i].y;
down[i].x=up[i].x; down[i].y=up[i].y-1.0;
}
solve();
}
return ;
}