题意:判断N条线段在某个方向的投影是否有存在公共点。
枚举所有点组成的直线 枚举时注意去重 判断是否存在一条直线都与已知线段相交 相交就输出 Yes! 否者输出No!
下面是代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define Max 105
#define eps 1e-10// 题目规定了精度是 1e-8 我用1e-10
using namespace std;
typedef struct
{
double x,y;
}point;
point P[2*Max];
int cnt;
typedef struct
{
point a,b;
}line;
line l[Max];
double Multi(point p1, point p2, point p0)//叉积
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
/*直线与线段的相交判断在线段的端点相交也是相交*/
bool Across(point a, point b, point c, point d)
{
double tmp = Multi(c, b, a) * Multi(d, b, a);
if (tmp < 0 || fabs(tmp) < eps) return true;
return false;
}
int Solve(int N)
{
int flag = 1;
for(int i = 0; i < cnt && flag;i++)//枚举两个不相同的点构成的直线与线段是否相交
for(int j = i+1; j < cnt && flag;j++)
{
if(P[i].x==P[j].x && P[i].y == P[j].y)continue;//处理重合点 这很重要 要不叉积判断会出错
int v = 1;
for(int k = 0; k < N && v; k++)
if(!Across(P[i], P[j], l[k].a,l[k].b)) v = 0;
if(v)flag = 0;
}
if(flag == 0)return 1;
else
return 0;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int T;
scanf("%d",&T);
while(T--)
{
cnt = 0;
int N;
scanf("%d",&N);
for(int i = 0; i < N;i++)
{
scanf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y);
P[cnt].x = l[i].a.x; P[cnt++].y = l[i].a.y;
P[cnt].x = l[i].b.x; P[cnt++].y = l[i].b.y;
}
if( Solve(N) )printf("Yes!\n");
else printf("No!\n");
}
return 0;
}