[poj] 3304 Segments || 判断线段相交

原题

给出n条线段,判断是否有一条直线与所有线段都有交点


若存在这样一条直线,那么一定存在一条至少过两个线段的端点的直线满足条件。
每次枚举两条线段的两个端点,确定一条直线,判断是否与其他线段都有交点。

判断交点:
判断AB和CD是否相交,即判断AC×BD(叉积)和AD×BC(叉积)是否同号

#include<cstdio>
#define eps 1e-13
#define N 110
using namespace std;
int t,n;
struct point
{
    double x,y;
    point() {}
    point(double _x,double _y) : x(_x),y(_y) {}
    double operator * (const point &b) const
	{
	    return x*b.y-b.x*y;
	}
    point operator - (const point &b) const
	{
	    return point(b.x-x,b.y-y);
	}
    bool operator == (const point &b) const
	{
	    return x==b.x && y==b.y;
	}
    void read()
	{
	    scanf("%lf%lf",&x,&y);
	}
};
struct hhh
{
    point s,t;
}a[N];

bool check(point aa,point bb)
{
    if (aa==bb) return 0;
    for (int i=1;i<=n;i++)
	if (((aa-a[i].s)*(aa-bb))*((aa-a[i].t)*(aa-bb))>eps) return 0;
    return 1;
}

bool solve()
{
    for (int i=1;i<=n;i++)
	for (int j=i+1;j<=n;j++)
	    if (check(a[i].s,a[j].t) || check(a[j].s,a[i].t)) return 1;
	    else if (check(a[i].s,a[j].s) || check(a[i].t,a[j].t)) return 1;
    return 0;
}

int main()
{
    scanf("%d",&t);
    while (t--)
    {
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	    a[i].s.read(),a[i].t.read();
	if (n<3 || solve()) puts("Yes!");
	else puts("No!");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/mrha/p/8168393.html