这题做了我两天,把问题复杂化了,其实只要判断枚举的直线与所有线段有没有交点即可,判断有没有交点用叉积,还有就是题目已经说了,距离小于1e-8算同一点,所以在枚举的时候,如果两个点距离小于1e-8,那么直接跳过这个点,枚举下一个点,因为这两个组成的是点,而不是一个向量。
//
// main.cpp
// Richard
//
// Created by 邵金杰 on 16/8/8.
// Copyright © 2016年 邵金杰. All rights reserved.
//
#include<iostream>
#include<vector>
#include<cmath>
#include<cstdio>
using namespace std;
#define EPS 1e-8
struct Point{
double x,y;
Point(double x,double y): x(x),y(y) {}
};
struct Vector{
double x,y;
Vector(double x,double y): x(x),y(y) {}
};
struct Line{
Point a,b;
Line(Point a,Point b): a(a),b(b) {}
};
vector<Point> ve;
vector<Line> le;
Vector operator - (Point p,Point q)
{
return Vector(p.x-q.x,p.y-q.y);
}
double cross(Vector p,Vector q)
{
return p.x*q.y-p.y*q.x;
}
double dist(Point p,Point q)
{
double x=p.x-q.x;
double y=p.y-q.y;
return hypot(fabs(x),fabs(y));
}
void work()
{
int lenv=(int)ve.size();
int lenl=(int)le.size();
for(int i=0;i<lenv;i++)
{
int s;
if(i%2==0) s=i+2;
else s=i+1;
for(int j=s;j<lenv;j++)
{
if(dist(ve[i],ve[j])<EPS) continue;
int ok=1;
for(int k=0;k<lenl;k++)
{
if(cross(le[k].a-ve[i],ve[j]-ve[i])*cross(le[k].b-ve[i],ve[j]-ve[i])>EPS)
{
ok=0;break;
}
}
if(ok) {cout<<"Yes!"<<endl;return ;}
}
}
cout<<"No!"<<endl;
}
int main()
{
int t,n;
double x1,y1,x2,y2;
scanf("%d",&t);
while(t--)
{
ve.clear();
le.clear();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
ve.push_back(Point(x1,y1));
ve.push_back(Point(x2,y2));
le.push_back(Line(Point(x1,y1),Point(x2,y2)));
}
if(n==1||n==2) cout<<"Yes!"<<endl;
else work();
}
}