poj 1039 Pipe (直线与线段相交判断+枚举端点)

版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/83833656

题目链接:传送门

题意:有一条宽度为1(指的是上下管壁纵坐标之差,不是管道真实的宽度)的折线形管道,管道壁不透光不反光,求从管道一头射入一束光线,光线在管道内沿直线传播最远能传播多远(横坐标能到达的最大值)。

输入:每个测试用例一个数据块,第一个整数为折点数(2到20之间),接下来每行一个折点坐标(即上图中的一个点[x,y],x互不相等,按增序排列),表示管道的上边界折点,对应的下边界折点为[x,y-1].折点数位0时表示输入结束。

输出:每次用例输出一行,若光线能穿透整个管道,输出Through all the pipe.否则输出能到达的x值,保留两位小数。

题解:直接枚举

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

struct point
{
    double x,y;
    point(){}
    point(double _x,double _y){
        x=_x;y=_y;
    }
};


point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator * (point a,double p) { return point(a.x*p,a.y*p);}
point operator / (point a,double p){ return point(a.x/p,a.y/p);}

bool operator < (const point &a,const point &b){
    return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-8;
int dcmp(double x){
    if(fabs(x)<esp) return 0;
    else return x<0?-1:1;
}
bool operator ==(const point &a,const point &b){
    return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}

double Cross(point A,point B) { return A.x*B.y-A.y*B.x;}

point Getlinenode(point P,point v,point Q,point w){ ///两参数方程求交点,(点,向量,点,向量)
    point u=P-Q;
    double t=Cross(w,u)/Cross(v,w);
    return P+v*t;
}

bool isCross(point s1,point e1,point s2,point e2)///判断直线与线段是否相交
{

    ///首先判断向量s2e2 跨立 向量s1e1
    double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);



    ///==0表示,相交于端点也认定为相交
    if(dcmp(c1*c2)>=0) return true;


    return false;
}

point p1[30],p2[30];
int main()
{

    int n;

    while(scanf("%d",&n)&&n)
    {
        double a,b;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&a,&b);
            p1[i]=point(a,b);
            p2[i]=point(a,b-1);
        }

        bool flag=true;

        double ans=p1[0].x;
        for(int i=0;i<n&&flag;i++)
        {
            for(int j=0;j<n&&flag;j++)
            {
                if(i==j) continue;

                int k;
                for( k=0;k<n;k++){
                    if(!isCross(p1[i],p2[j],p1[k],p2[k])){ ///判断直线ij与线段k是否相交
//                            
                        break;
                    }
                }

                if(k==n) {
                    flag=false;break;
                }
                else if(k>max(i,j)){
                    point item=Getlinenode(p1[i],p1[i]-p2[j],p1[k],p1[k]-p1[k-1]); 
                    if(item.x>ans) ans=item.x;
                    item=Getlinenode(p1[i],p1[i]-p2[j],p2[k],p2[k]-p2[k-1]);
                   if(item.x>ans) ans=item.x;
//                    printf("ans=%.2f,k=%d\n",ans,k);
                }
            }
        }

        if(flag){
            printf("%.2f\n",ans);
        }
        else printf("Through all the pipe.\n");
    }
    return 0;
}















猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/83833656