poj 1039 Pipe(叉乘。。。)
题目:http://poj.org/problem?id=1039
题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道.
思路:最优的是 光线过一个上顶点,一个下顶点。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<iomanip> 5 using namespace std; 6 const double eps=1e-8; 7 const int INF=1<<28; 8 int n; 9 10 struct point 11 { 12 double x,y; 13 }up[100],down[100]; 14 15 int dblcmp(double x) 16 { 17 if(x<-eps) return -1;//一定要注意精度问题,不然样例都过不了 18 if(x>eps) return 1; 19 return 0; //在这里把接近0的数值都看成了0,实际这些数值就是0 20 } 21 22 double det(double x1,double y1,double x2,double y2)// 向量坐标点的叉乘 23 { 24 return x1*y2-x2*y1; 25 } 26 double cross(point a,point b,point c)//ab和ac向量的叉乘 27 { 28 return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y); 29 } 30 31 double getx(point a,point b,point c,point d)//求ab和cd组成的直线交点的横坐标。 32 { 33 double b1,b2,k1,k2; 34 k1=(b.y-a.y)/(b.x-a.x); 35 k2=(d.y-c.y)/(d.x-c.x); 36 b1=a.y-k1*a.x; 37 b2=c.y-k2*c.x; 38 return (b2-b1)/(k1-k2); 39 } 40 void solve() 41 { 42 int i,j,k; 43 double ans=-INF,cnt; 44 for(i=0; i<n; i++) 45 { 46 for(j=0; j<n; j++) 47 { 48 if(i==j) continue; //同一个横坐标的跳过 49 for(k=0; k<n; k++) 50 { 51 if(dblcmp(cross(up[i],down[j],up[k]))*dblcmp(cross(up[i],down[j],down[k]))>0) 52 break;//叉乘大于0说明 这条直线在两个点的同一侧,从叉乘的定义可以看出|a||b|sin&; 53 } 54 if(k<max(i,j)) continue; //如果这样的话 说明光线不存在。。。 55 cnt=getx(up[i],down[j],up[k],up[k-1]);//找上顶点线的交点 56 if(cnt>ans) ans=cnt; 57 cnt=getx(up[i],down[j],down[k],down[k-1]);//找下顶点线的交点 58 if(cnt>ans) ans=cnt; 59 if(k==n) 60 { 61 cout<<"Through all the pipe."<<endl; 62 return; 63 } 64 } 65 } 66 cout<<fixed<<setprecision(2)<<ans<<endl; 67 } 68 int main() 69 { 70 int i; 71 while(~scanf("%d",&n)&&n) 72 { 73 for(i=0; i<n; i++) 74 { 75 cin>>up[i].x; cin>>up[i].y; 76 down[i].x=up[i].x; down[i].y=up[i].y-1.0; 77 } 78 solve(); 79 } 80 return 0; 81 }