注意判断大于 小于 等于0的时候
要用eps 而不是用0
见cross相乘判断 用0即WA
/* 尝试 向量,点都用Point表示 */ #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define db double using namespace std; const db eps=1e-8; const int N=150; struct Point { db x,y; Point(){} Point(db _x,db _y) {x = _x;y = _y;} }; struct Line { Point s,e; Line(){} Line(Point _s,Point _e) {s=_s;e=_e;} }; Line L[N]; Point operator + (Point A,Point B) {return Point(A.x+B.x,A.y+B.y);} Point operator - (Point A,Point B) {return Point(A.x-B.x,A.y-B.y);} db operator * (Point A,Point B) {return A.x*B.x+A.y*B.y;} db operator ^ (Point A,Point B) {return A.x*B.y-A.y*B.x;} db dist(Point s,Point e) {return sqrt((s-e)*(s-e));} db cross(Point a,Point b,Point c) {return (a-c)^(b-c);} int n; bool check(Point s,Point e) { if(dist(s,e)<=eps) return 0; for(int i=1;i<=n;i++) if(cross(L[i].s,s,e)*cross(L[i].e,s,e)>eps) return 0; return 1; } /* 题目转化为求是否存在一条直线与所有线段相交 巧妙的枚举两个线段的端点来确定一条直线 然后判断该直线是否与全部线段有交点 */ int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { db x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); L[i]=Line(Point(x1,y1),Point(x2,y2)); } bool flag=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(check(L[i].s,L[j].s)||check(L[i].s,L[j].e) ||check(L[i].e,L[j].s)||check(L[i].e,L[j].e)) { flag=1;break; } if(flag) puts("Yes!"); else puts("No!"); } return 0; }