hdu 1086(判断线段相交)

 

传送门:You can Solve a Geometry Problem too

题意:给n条线段,判断相交的点数。

分析:判断线段相交模板题,快速排斥实验原理就是每条线段代表的向量和该线段的一个端点与 另一条线段的两个端点构成的两个向量求叉积,如果线段相交那么另一条线段两个端点必定在该线段的两边,则该线段代表的向量必定会顺时针转一遍逆时针转一遍,叉积必定会小于等于0,同样对另一条线段这样判断一次即可。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#define N 1010
#define PI acos(-1.0)
using namespace std;
const double eps=1e-8;
int sgn(double x)
{
    if(fabs(x)<eps)return 0;
    if(x<0)return -1;
    return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y):x(_x),y(_y){}
    Point operator -(const Point &a)const
    {
        return Point(x-a.x,y-a.y);
    }
    double operator *(const Point &a)const
    {
        return a.x*x+a.y*y;
    }
    double operator ^(const Point &a)const
    {
        return x*a.y-y*a.x;
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e):s(_s),e(_e){}
};
bool segcrossseg(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&
    max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&
    max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&
    max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&
    sgn((l1.s-l1.e)^(l2.s-l1.e))*sgn((l1.s-l1.e)^(l2.e-l1.e))<=0&&
    sgn((l2.s-l2.e)^(l1.s-l2.e))*sgn((l2.s-l2.e)^(l1.e-l2.e))<=0;
}
Line L[110];
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        for(int i=1;i<=n;i++)
        {
            double a,b,c,d;
            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
            L[i]=Line(Point(a,b),Point(c,d));
        }
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            if(segcrossseg(L[i],L[j]))ans++;
        printf("%d\n",ans);
    }
}
View Code

 

posted on 2015-03-11 22:28  lienus  阅读(153)  评论(0编辑  收藏  举报

导航