题目:Segments
// 题目求是否满足所有给定的线段在一条直线上有一个公共的投影点
// 对于某一条直线而言,过这个点有一条垂线,那么所有的线段必定与垂线有交点
// 当这条垂线还没有确定的时候,我们可以通过一条一条线段确定垂线旋转的范围
// 而这些范围的极限就是某条或者某两条线段的端点
// 因此我们要做的是枚举线段的端点看是否存在一条直线与所有线段均相交
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define eps 1e-10
using namespace std;
struct point
{
double x,y;
};
struct line
{
point sp,ep;
};
line l[110];
int n;
double xmulti(point p1,point p2,point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool is_ok(point a,point b)
{
if(dis(a,b)<eps)
return 0;
for(int i=1;i<=n;i++)
if(xmulti(a,l[i].sp,b)*xmulti(a,l[i].ep,b)>eps)
return false;
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf%lf%lf%lf",&l[i].sp.x,&l[i].sp.y,&l[i].ep.x,&l[i].ep.y);
int ans=0;
if(n==1)
ans=1;
else
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(is_ok(l[i].sp,l[j].sp)||is_ok(l[i].sp,l[j].ep)
||is_ok(l[i].ep,l[j].ep)||is_ok(l[i].ep,l[j].sp))
{
ans=1;
break;
}
}
if(ans)
break;
}
}
if(ans)
printf("Yes!\n");
else
printf("No!\n");
}
return 0;
}