首先题中的要求等价于:存在一条直线l和所有的线段都相交。
证明:若存在一条直线l和所有线段相交,作一条直线m和l垂直,则m就是题中要求的直线,所有线段投影的一个公共点即为垂足。(l和每条线段的交点沿l投影到m上的垂足处)
反过来,若存在m,所有线段在m上的投影有公共点,则过这点垂直于m作直线l,l一定和所有线段相交。

然后证存在l和所有线段相交等价于存在l过某两条线段的各一个端点且和所有线段相交。
充分性显然。必要性:若有l和所有线段相交,则可保持l和所有线段相交,左右平移l到和某一线段交于端点停止("移不动了")。然后绕这个交点旋转。也是转到"转不动了"(和另一线段交于其一个端点)为止。这样就找到了一个新的l。

于是本题可归结为枚举两两线段的各一个端点,连一条直线,再判断剩下的线段是否都和这条直线有交点。

细节: You must assume that two floating point numbers a and b are equal if |a - b| < 10^-8.
单条直线必 Yes

1
2 #include < stdio.h >
3 #include < stdlib.h >
4 #include < math.h >
5 #define N 101
6 #define MAXN 1000
7 #define offset 10000
8 #define eps 1e-8
9 #define zero(x) (((x)>0?(x):-(x))<eps)
10 #define _sign(x) ((x)>eps?1:((x)<-eps?2:0))
11 struct point { double x,y;} ;
12 struct line {point a,b;} ;
13
14 int n;
15 line arr[N];
16
17 double xmult(point p1,point p2,point p0) {
18 return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
19 }

20 int same_side(point p1,point p2,point l1,point l2) {
21 return xmult(l1,p1,l2) * xmult(l1,p2,l2) > eps;
22 }

23
24 int IsConver( int i, int j,point a,point b) {
25 int step;
26 for (step = 0 ;step < n;step ++ )
27 if (step != i && step != j) {
28 if (same_side(arr[step].a,arr[step].b,a,b)) return 0 ;
29 }

30 return 1 ;
31 }

32
33 int Find() {
34 int i,j,flag;
35 flag = 0 ;
36 for (i = 0 ;i < n;i ++ )
37 for (j = 0 ;j < n;j ++ ) {
38 if (i != j) {
39 flag = 1 ;
40 if (
41 ! zero(sqrt((arr[i].a.x - arr[j].a.x) * (arr[i].a.x - arr[j].a.x) + (arr[i].a.y - arr[j].a.y) * (arr[i].a.y - arr[j].a.y))) &&
42 IsConver(i,j,arr[i].a,arr[j].a)
43 )
44 return 1 ;
45
46 if (
47 ! zero(sqrt((arr[i].b.x - arr[j].b.x) * (arr[i].b.x - arr[j].b.x) + (arr[i].b.y - arr[j].b.y) * (arr[i].b.y - arr[j].b.y))) &&
48 IsConver(i,j,arr[i].b,arr[j].b)
49 )
50 return 1 ;
51
52 if (
53 ! zero(sqrt((arr[i].a.x - arr[j].b.x) * (arr[i].a.x - arr[j].b.x) + (arr[i].a.y - arr[j].b.y) * (arr[i].a.y - arr[j].b.y))) &&
54 IsConver(i,j,arr[i].a,arr[j].b)
55 )
56 return 1 ;
57
58 if (
59 ! zero(sqrt( (arr[i].b.x - arr[j].a.x) * (arr[i].b.x - arr[j].a.x) + (arr[i].b.y - arr[j].a.y) * (arr[i].b.y - arr[j].a.y))) &&
60 IsConver(i,j,arr[i].b,arr[j].a)
61 )
62 return 1 ;
63
64 }

65 }

66 if (flag == 0 ) return 1 ;
67 else return 0 ;
68 }

69
70 int main() {
71 int t,_case,i,j,step;
72 scanf( " %d " , & t);
73 for (_case = 0 ;_case < t;_case ++ ) {
74 scanf( " %d " , & n);
75 for (i = 0 ;i < n;i ++ )
76 scanf( " %lf%lf%lf%lf " , & arr[i].a.x, & arr[i].a.y, & arr[i].b.x, & arr[i].b.y);
77
78 if (Find()) printf( " Yes!\n " );
79 else printf( " No!\n " );
80 }

81 return 0 ;
82 }

83