首先題中的要求等價于:存在一條直線l和所有的線段都相交。
證明:若存在一條直線l和所有線段相交,作一條直線m和l垂直,則m就是題中要求的直線,所有線段投影的一個公共點即為垂足。(l和每條線段的交點沿l投影到m上的垂足處)
反過來,若存在m,所有線段在m上的投影有公共點,則過這點垂直于m作直線l,l一定和所有線段相交。
然后證存在l和所有線段相交等價于存在l過某兩條線段的各一個端點且和所有線段相交。
充分性顯然。必要性:若有l(wèi)和所有線段相交,則可保持l和所有線段相交,左右平移l到和某一線段交于端點停止("移不動了")。然后繞這個交點旋轉。也是轉到"轉不動了"(和另一線段交于其一個端點)為止。這樣就找到了一個新的l。
于是本題可歸結為枚舉兩兩線段的各一個端點,連一條直線,再判斷剩下的線段是否都和這條直線有交點。
細節(jié): 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