首先題中的要求等價于:存在一條直線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