POJ3304 Segments

题意

求是否存在⼀条直线,使得所有线段在其上面的投影有至少⼀个 ⼀个交点。

假如存在交点,那么从这个交点做垂线,该垂线过所有线段,因此我们需要判断是否存在一条直线过所有线段,这种直线中必定有一条两端点都是给出的线段的端点,\(O(n^2)\)枚举判断即可。

code:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=110;
const double eps=1e-8;
int T,n;
bool flag;
struct Point
{
    double x,y;
    Point(double _x=0,double _y=0){x=_x,y=_y;}
    inline double len(){return sqrt(x*x+y*y);}
    Point operator+(const Point a)const{return Point(x+a.x,y+a.y);}
    Point operator-(const Point a)const{return Point(x-a.x,y-a.y);}
    Point operator*(double k)const{return Point(x*k,y*k);}
	Point operator/(double k)const{return Point(x/k,y/k);}
    double operator*(const Point a)const{return x*a.y-y*a.x;}
    double operator&(const Point a)const{return x*a.x+y*a.y;}
};
inline int dcmp(double x)
{
	if(fabs(x)<=eps)return 0;
	return x<0?-1:1;
}
struct Line
{
	Point p,v;
	Line(Point _p=Point(0,0),Point _v=Point(0,0)){p=_p;v=_v;}
}l[maxn];
inline Point get(Point a,Point b){return b-a;}
inline bool check(Line a,Line b){return dcmp((get(a.p,b.p)*get(a.p,a.v))*(get(a.p,b.v)*get(a.p,a.v)))<=0;}
inline bool check_line(Line a)
{
	if(!dcmp((a.p-a.v).len()))return 0;
	int cnt=0;
	for(int i=1;i<=n;i++)cnt+=check(a,l[i]);
	return cnt==n;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		flag=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%lf%lf%lf%lf",&l[i].p.x,&l[i].p.y,&l[i].v.x,&l[i].v.y);
		for(int i=1;i<=n;i++)
			for(int j=i;j<=n;j++)
				if(check_line(Line(l[i].p,l[j].p))||check_line(Line(l[i].p,l[j].v))
				||check_line(Line(l[i].v,l[j].p))||check_line(Line(l[i].v,l[j].v)))
					flag=1;
		puts(flag?"Yes!":"No!");
	}
	return 0;
}
posted @ 2020-01-17 08:58  nofind  阅读(92)  评论(0编辑  收藏  举报