开始看错了题意,以为是要投影到其中一条线段上,WA N次。。ORZ~
实际的意思是,投影到任意条直线上都可以,只要投影间有交点即可。那么过这条被投影的直线做垂线,垂线必过所有的线段。
如何求出垂线呢?因为垂线与所有线段相交,在保证相交的前提下旋转,那么最终会定于两线段端点。那么枚举端点,在对所有线段做跨立验证即可
//Memory: 204K
//Time: 32MS
#include <iostream>
#include <math.h>
#define EP 1E-8
using namespace std;
struct POINT
{
double x,y;
};
struct LINESEG
{
POINT s,e;
};LINESEG l[104];POINT p[210];
double multiply(POINT p1,POINT p2,POINT p0) //点积
{
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
/* 线段v所在直线与线段u相交时返回true
判断线段u是否跨立线段v */
bool intersect_l(LINESEG u,LINESEG v)
{
return multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0;
}
int main()
{
int cas,n;
cin>>cas;
while(cas--)
{
bool flag=false;
cin>>n;
int i,j,k,sum=1;
LINESEG lin;
for(i=1;i<=n;i++)
{
cin>>l[i].s.x>>l[i].s.y>>l[i].e.x>>l[i].e.y;
p[sum++]=l[i].s;
p[sum++]=l[i].e;
}
if(n==1 || n==2)
{
flag=true;
cout<<"Yes!"<<endl;
continue;
}
for(i=1;i<sum;i++)
{
for(j=1;j<sum;j++)
{
if(fabs(p[i].x-p[j].x)<EP && fabs(p[i].y-p[j].y)<EP)
continue;
lin.s=p[i];
lin.e=p[j];
for(k=1;k<=n;k++)
if(!intersect_l(l[k],lin))
break;
if(k==n+1)
{
flag=true;
break;
}
}
if(flag)
break;
}
if(flag)
cout<<"Yes!"<<endl;
else
cout<<"No!"<<endl;
}
}