Pipe 计算几何基础

题意:

题目链接1题目链接2
大概就是给你一些管道,求光从管口处射入最多能射多远

思路:

枚举拐点(上壁与下壁都算)作为直线(光束)上的两个点。然后判断这条直线和每一条线段\((x_i, y_i)(x_i, y_i - 1)\)是否有交点。若无,则求出最远能到达的x。

注意事项:

丧心病狂的卡精度
不能直接跟0比较,而应是eps(好像本来就该这样吧。。。)
考虑精度误差,以及各种细节

code:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=30;
const double eps=1e-7;
struct point{double x,y;}e1[N],e2[N];
inline double lfabs(double x){if(x<-eps)x=-x;return x;}
bool operator==(point x,point y){return (lfabs(x.x-y.x)<eps)&&(lfabs(x.y-y.y)<eps);}
point operator-(point x,point y){return (point){x.x-y.x,x.y-y.y};}
double operator^(point x,point y){return x.x*y.y-x.y*y.x;}
double ans;
int n;
inline double inc(point p1,point p2,point u,point v)
{
    return (((p1-u)^(p2-u))*((p1-v)^(p2-v)));//线段与直线判断交点情况
}
inline double slv_inc(point p1,point p2,point u,point v)
{
    double s1=(u-p1)^(v-p1),s2=(v-p2)^(u-p2);
    double anss=p2.x+(p1.x-p2.x)*s2/(s1+s2);
    return anss;
}
int main()
{
    while(7)
    {
        scanf("%d",&n);
        if(!n) break;
        for(int i=1;i<=n;++i)
        {
            scanf("%lf%lf",&e1[i].x,&e1[i].y);
            e2[i]=e1[i]-(point){0.0,1.0};
        }
        bool pd=0;
        int nn=n<<1;ans=e1[1].x;
        for(int i=1;i<=nn&&(!pd);++i)
            for(int j=i+1;j<=nn;++j)
            {
                point p1=i<=n?e1[i]:e2[i-n];
                point p2=j<=n?e1[j]:e2[j-n];
                if(p1.x>p2.x) swap(p1,p2);
                bool flag=0;int pos=0;
                for(int k=1;k<=n;++k)
                {
                    if(e1[k]==p1||e1[k]==p2||e2[k]==p1||e2[k]==p2) continue;
                    if(e1[k].x-p2.x>eps){pos=k;break;}
                    if(inc(p1,p2,e1[k],e2[k])>eps){flag=1;break;}
                }
                if(flag) continue;
                while(inc(p1,p2,e1[pos],e2[pos])<eps&&pos<=n)++pos;
                if(pos>n||pos==0){puts("Through all the pipe.");pd=1;break;}
                if(inc(p1,p2,e1[pos],e1[pos-1])<eps)ans=max(ans,slv_inc(p1,p2,e1[pos],e1[pos-1]));
                if(inc(p1,p2,e2[pos],e2[pos-1])<eps)ans=max(ans,slv_inc(p1,p2,e2[pos],e2[pos-1]));
            }
        if(pd) continue;
        printf("%.2f\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zmyzmy/p/12218608.html