题意:给你一些线段,然后问你是否存在一条直线,把这些线段投影到直线上,所投影与原线段至少有1个公共点。
思路:由题意可得原线段与直线符合条件的直线至少有1个公共点,所以就转化成是否有直线与所有线段相交的问题了。枚举任意两个不同端点作为直线上两点确定一直线判断是否与所有直线相交即可。
吐槽:距离小于10e-8的点看作相同点。。。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double x[205],y[205];
int t,n;
int s;
int ans;
bool can(int i,int j)
{
for(int k=0;k<n;k++)
{
if(((x[2*k]-x[i])*(y[j]-y[i])-(y[2*k]-y[i])*(x[j]-x[i])>0&&(x[2*k+1]-x[i])*(y[j]-y[i])-(y[2*k+1]-y[i])*(x[j]-x[i])>0)||((x[2*k]-x[i])*(y[j]-y[i])-(y[2*k]-y[i])*(x[j]-x[i])<0&&(x[2*k+1]-x[i])*(y[j]-y[i])-(y[2*k+1]-y[i])*(x[j]-x[i])<0))return false;
}
return true;
}
void solve()
{
for(int i=0;i<s;i++)
{
for(int j=i+1;j<s;j++)
{
if(sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))<10e-8)continue;
if(can(i,j))
{
ans=1;
return;
}
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
s=2*n;
for(int i=0;i<s;i++)
{
scanf("%lf%lf",&x[i],&y[i]);
}
ans=0;
solve();
if(ans)cout<<"Yes!"<<endl;
else cout<<"No!"<<endl;
}
return 0;
}