标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 9439 | Accepted: 2854 |
Description
Input
Output
Sample Input
4 0 1 2 2 4 1 6 4 6 0 1 2 -0.6 5 -4.45 7 -5.57 12 -10.8 17 -16.55 0
Sample Output
4.67 Through all the pipe.
题意:求光线通过管道的最远坐标
思路:能通过最远的一条光线一定经过一个up[i]和一个down[j],枚举即可。通过判断直线up[i]down[j]是否与第k个管口线段up[k]down[k]相交来判断是否能通过管口k,从小到大遍历,当碰到不能通过时,即能通过第k-1个而不能通过第k个,最远坐标一定在xk和xk-1之间,光线与k-1和k之间的上下管壁交点横坐标的最大值。
判断直线与线段相交用叉积来判断左右拐从而判断相交,求直线与线段交点则用定比分点,其中线段长度比值用叉积求面积比代替
hack点:求直线与线段交点时需先排除直线与线段不相交的情况
#include<iostream> #include<stdio.h> #include<cstring> #include<math.h> #include<stdlib.h> #include<algorithm> using namespace std; const int maxn=1000100; const int INF=(1<<29); const double eps=0.00000001; int n; struct Point { double x,y; friend double operator*(const Point A,const Point B) { return A.x*B.y-A.y*B.x; } friend Point operator-(const Point A,const Point B) { return {A.x-B.x,A.y-B.y}; } }; Point up[maxn],down[maxn]; double MAX(double a,double b) { return a>b+eps?a:b; } bool intersect(Point A,Point B,Point C,Point D)///判断直线AB是否与线段CD相交 { if(((C-A)*(B-A))*((D-A)*(B-A))<eps) return true; return false; } Point inter_point(Point A,Point B,Point C,Point D)///返回直线AB和线段CD的交点 { if(!intersect(A,B,C,D)) return {-INF*1.0,0};///判断直线AB是否与线段CD相交,不相交必须须特判 double area1=fabs((B-A)*(C-A)); double area2=fabs((B-A)*(D-A)); double x=(area1*D.x+area2*C.x)/(area1+area2); double y=(area1*D.y+area2*C.y)/(area1+area2); return {x,y}; } int main() { while(cin>>n,n){ for(int i=0;i<n;i++){ cin>>up[i].x>>up[i].y; down[i]={up[i].x,up[i].y-1.0}; } double ans=-INF*1.0; bool flag=0; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==j) continue; if(!intersect(up[i],down[j],up[0],down[0])) continue; for(int k=1;k<n;k++){ if(!intersect(up[i],down[j],up[k],down[k])){ Point A=inter_point(up[i],down[j],up[k-1],up[k]); Point B=inter_point(up[i],down[j],down[k-1],down[k]); double Max=MAX(A.x,B.x); if(Max>ans+eps) ans=Max; //cout<<"i="<<i<<" j="<<j<<" k="<<k<<" Max="<<Max<<" A= "<<A.x<<" "<<A.y<<" B= "<<B.x<<" "<<B.y<<endl; break; } else if(k==n-1){ flag=1;break; } } if(flag) break; } if(flag) break; } if(flag) printf("Through all the pipe.\n"); else printf("%.2f\n",ans); } return 0; }
poj1039——计算几何 求直线与线段交点,判断两条直线是否相交
标签:
原文地址:http://www.cnblogs.com/--560/p/4387755.html