• POJ 3304 Segments 判断直线和线段相交


    POJ 3304  Segments

    题意:给定n(n<=100)条线段,问你是否存在这样的一条直线,使得所有线段投影下去后,至少都有一个交点。

    思路:对于投影在所求直线上面的相交阴影,我们可以在那里作一条线,那么这条线就和所有线段都至少有一个交点,所以如果有一条直线和所有线段都有交点的话,那么就一定有解。

    怎么确定有没直线和所有线段都相交?怎么枚举这样的直线?思路就是固定两个点,这两个点在所有线段上任意取就可以,然后以这两个点作为直线,去判断其他线段即可。为什么呢?因为如果有直线和所有线段都相交,那么我绝对可以平移到某个极限的端点位置,再旋转到某个极限的端点位置,也不会失去正解。Bug点就是枚举的两个点是重点的话,这个直线的方向向量是0向量,这样会判断到与所有线段都相交。~~

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    
    const int maxn = 5000+20;
    struct coor
    {
        double x,y;
        coor(){}
        coor(double xx,double yy):x(xx),y(yy){}
        double operator ^(coor rhs) const //计算叉积(向量积)
        {
            return x*rhs.y - y*rhs.x;
        }
        coor operator -(coor rhs) const //坐标相减,a-b得到向量ba
        {
            return coor(x-rhs.x,y-rhs.y);
        }
        double operator *(coor rhs) const //数量积
        {
            return x*rhs.x + y*rhs.y;
        }
    };
    const double eps = 1e-8;
    struct Line
    {
        coor point1,point2;
        Line(){}
        Line(coor xx,coor yy):point1(xx),point2(yy){}
        bool operator &(Line rhs) const //判断直线和rhs线段是否相交
        {
            //自己表示一条直线,然而rhs表示的是线段
            //思路,判断rhs线段上两个端点是否在this直线的同一侧即可,用一侧,就不相交
            coor ff1 = point2 - point1; //直线的方向向量
            return ( ((rhs.point1-point1)^ff1) * ((rhs.point2-point1)^ff1) ) <= 0;//符号不同或者有0,证明相交
        }
    }a[maxn];
    int n;
    
    bool same (double a,double b)
    {
        return fabs(a-b)<eps;
    }
    bool check (coor aa,coor bb)
    {
        Line t = Line(aa,bb);
        for (int i=1;i<=n;++i)
        {
            if (!(t&a[i]))
            {
                return false;
            }
        }
        return true;
    }
    void work ()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;++i)
        {
            scanf("%lf%lf%lf%lf",&a[i].point1.x,&a[i].point1.y,&a[i].point2.x,&a[i].point2.y);
        }
        if (n==1)
        {
            printf ("Yes!
    ");
            return ;
        }
        for (int i=1;i<=n;++i)
        {
            for (int j=i+1;j<=n;++j)
            {
                if (check(a[i].point1,a[j].point1))
                {
                    printf ("Yes!
    ");
                    return ;
                }
                if (check(a[i].point1,a[j].point2))
                {
                    printf ("Yes!
    ");
                    return ;
                }
                if (check(a[i].point2,a[j].point1))
                {
                    printf ("Yes!
    ");
                    return ;
                }
                if (check(a[i].point2,a[j].point2))
                {
                    printf ("Yes!
    ");
                    return ;
                }
            }
        }
        printf ("No!
    ");
        return ;
    }
    
    int main()
    {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        int t;
        scanf("%d",&t);
        while(t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    Linux 常用工具openssh之ssh-copy-id
    Linux 常用工具openssh之ssh-agent
    SpringMVC视图机制详解[附带源码分析]
    Spring中Ordered接口简介
    SpringMVC拦截器详解[附带源码分析]
    SpringMVC类型转换、数据绑定详解[附带源码分析]
    详解SpringMVC请求的时候是如何找到正确的Controller[附带源码分析]
    详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
    SpringMVC关于json、xml自动转换的原理研究[附带源码分析]
    Servlet容器Tomcat中web.xml中url-pattern的配置详解[附带源码分析]
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5759295.html
Copyright © 2020-2023  润新知