题意可以转换为求有没有一条直线,这条直线必须要和所有的线段都相交。。
然后有个结论就是如果能找到一条直线能够穿过所有的线段那么肯定能找到一条穿过所有线段的直线必过其中的两个端点
那么这样就好做了,我们可以直接枚举两个端点,然后判断这两个端点的直线是否穿过所有的线段就可以了。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
double EPS = 1e-11;
double add(double a,double b){
if(abs(a+b)<EPS*(abs(a)+abs(b)))
return 0;
return a+b;
}
struct P{
double x,y;
P() {}
P(double x,double y) : x(x),y(y){
}
P operator +(P p){
return P(add(x,p.x),add(y,p.y));
}
P operator -(P p){
return P(add(x,-p.x),add(y,-p.y));
}
P operator *(double d){
return P(x*d,y*d);
}
double dot(P p){
return add(x*p.x,y*p.y);
}
double det(P p){
return add(x*p.y,-y*p.x);
}
};
P q[100000],p[100000],r[100000];
int t,n,ans=0;
bool equ(P a,P b)
{
if(fabs(a.x-b.x)<=EPS && fabs(a.y-b.y)<=EPS)
return 1;
return 0;
}
bool judge(P a,P b)
{
if(equ(a,b))
return 0;
for(int i=0;i<n;i++)
{
if((q[i]-a).det(b-a)*(p[i]-a).det(b-a)>EPS)
return 0;
}
return 1;
}
int main()
{
scanf("%d",&t);
while(t--)
{
int fg=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&q[i].x,&q[i].y,&p[i].x,&p[i].y);
}
if(n==1 || n==2)
{
printf("Yes!\n");
continue;
}
for(int i=0;i<n;i++)
{
if(fg)
break;
for(int j=i+1;j<n;j++)
{
if(judge(q[i],q[j]) || judge(q[i],p[j]) || judge(q[j],p[i]) || judge(p[i],p[j]))
{
fg=1;
break;
}
}
}
if(fg)
printf("Yes!\n");
else
printf("No!\n");
}
return 0;
}