如果存在一条穿过所有线段的直线,那么这条直线的垂线就满足题意了。
如果存在一条穿过所有线段的直线,那么存在一条穿过所有线段,且穿过了不同线段的两个端点的这样一条直线。
算几真TM烦各种细节各种挂精度。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 205 #define eps 1e-8 using namespace std; struct point { double x,y; point (double x,double y):x(x),y(y) {} point () {} friend point operator -(point x,point y) { return point(x.x-y.x,x.y-y.y); } }p[maxn]; struct line { point x,dt; line (point x,point dt):x(x),dt(dt) {} friend double operator *(line x,line y) { return x.dt.x*y.dt.y-x.dt.y*y.dt.x; } line () {} }l[maxn]; int t,n; double x1x,y1y,x2x,y2y; double get_y(double x,line y) { double k=(x-y.x.x)/(y.dt.x); return y.x.y+k*y.dt.y; } bool check(line x,line y) { if (!x.dt.x) { if (!y.dt.x) return (fabs(x.x.x-y.x.x)<eps); else { double mn=min(y.x.x,y.x.x+y.dt.x),mx=max(y.x.x,y.x.x+y.dt.x); return ((x.x.x>=mn) && (x.x.x<=mx)); } } else { double y1=get_y(y.x.x,x),y2=get_y(y.x.x+y.dt.x,x); return (y1-y.x.y)*(y2-(y.x.y+y.dt.y))<=eps; } } bool work() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&x1x,&y1y,&x2x,&y2y); p[2*i-1]=point(x1x,y1y);p[2*i]=point(x2x,y2y); l[i]=line(p[2*i-1],p[2*i]-p[2*i-1]); } for (int i=1;i<=2*n;i++) for (int j=i+1;j<=2*n;j++) { line now=line(p[i],p[j]-p[i]);int flag=1; for (int k=1;k<=n;k++) if (!check(now,l[k])) {flag=0;break;} if (flag) return true; } return false; } int main() { scanf("%d",&t); for (int i=1;i<=t;i++) { if (work()) printf("Yes! "); else printf("No! "); } return 0; }