题意:给一个管道求光线能穿到的最大x坐标。
解法:通过旋转光线一定可以使得光线接触一个上点和一个下点。枚举接触的上下点,然后逐一判断光线是否穿过每个拐点面。碰到一个拐点面没有穿过的,则是因为与其左边线段相交,求出直线与线段交点更新答案即可。不想交则说明在前一个拐点已经穿出去了。
代码:
/****************************************************** * author:xiefubao *******************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <string.h> //freopen ("in.txt" , "r" , stdin); using namespace std; #define eps 1e-10 const double pi=acos(-1.0); typedef long long LL; const int Max=10100; const int INF=1000000007; struct point { double x,y; } points1[30],points2[30]; int n; int mult(point a,point b,point c) { a.x-=c.x; a.y-=c.y; b.x-=c.x; b.y-=c.y; double tool=a.x*b.y-a.y*b.x; if(abs(tool)<=eps) return 0; if(tool<0) return -1; return 1; } double mult2(point a,point b,point c) { a.x-=c.x; a.y-=c.y; b.x-=c.x; b.y-=c.y; return a.x*b.y-a.y*b.x; } bool OK(point p1,point p2,int i) { return mult(p1,p2,points1[i])*mult(p1,p2,points2[i])<=0; } bool inter(point p1,point p2,point p3,point p4) { if(mult(p1,p2,p3)*mult(p1,p2,p4)<0) return true; return false; } double getx(point p1,point p2,point p3,point p4) { double area1=abs(mult2(p1,p2,p3)),area2=abs(mult2(p1,p2,p4)); return area1/(area1+area2)*p4.x+area2/(area1+area2)*p3.x; } double solve(point p1,point p2) { if(!OK(p1,p2,0)) return points1[0].x; for(int i=1; i<n; i++) { if(!OK(p1,p2,i)) { if(inter(p1,p2,points1[i-1],points1[i])) return getx(p1,p2,points1[i-1],points1[i]); if(inter(p1,p2,points2[i-1],points2[i])) return getx(p1,p2,points2[i-1],points2[i]); return points1[i-1].x; } } return points1[n-1].x; } int main() { while(scanf("%d",&n)==1&&n) { for(int i=0; i<n; i++) { scanf("%lf%lf",&points1[i].x,&points1[i].y); points2[i].x=points1[i].x; points2[i].y=points1[i].y-1.0; } double ans=points1[0].x; for(int i=0; i<n; i++) for(int j=0; j<n; j++) { if(i==j)continue; ans=max(ans,solve(points1[i],points2[j]));//cout<<i<<" "<<j<<" "<<solve(points1[i],points2[j])<<endl; } if(abs(ans-points1[n-1].x)<eps) printf("Through all the pipe.\n"); else printf("%.2f\n",ans); } return 0; } /* 4 0 1 1 2 2 1 3 -1 4 -301 1 -254 8 -196 3 -52 13 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 */
poj1039(计算几何)线段相交
时间: 2024-10-13 12:36:56