很郁闷的一题,第一次碰到使用不同的编译器,一个超时(C++),一个AC的情况(G++)。。。
首先题中的要求等价于:存在一条直线l和所有的线段都相交。
证明:若存在一条直线l和所有线段相交,作一条直线m和l垂直,则m就是题中要求的直线所有线段投影的一个公共点即为垂足。(l和每条线段的交点沿l投影到m上的垂足处)反过来,若存在m,所有线段在m上的投影有公共点,则过这点垂直于m作直线l, l一定和所有线段相交。
然后证存在l和所有线段相交等价于存在l过某两条线段的各一个端点且和所有线段相交。充分性显然。必要性:若有l和所有线段相交,则可保持l和所有线段相交,左右平移l到和某一线段交于端点停止(“移不动了”)。然后绕这个交点旋转。也是转到“转不动了”(和另一线段交于其一个端点)为止。这样就找到了一个新的l。
于是本题可归结为枚举两两线段的各一个端点,连一条直线,再判断剩下的线段是否都和这条直线有交点。
注意:数据中有所有线段都缩成一个点的情况。
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
#include<cstdio>
2
#include<cstring>
3
#include<algorithm>
4
#include<vector>
5
#include<complex>
6
#include<cmath>
7
#include<iostream>
8
using namespace std;
9![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
10
typedef complex<double> point;
11![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
12
const int maxn = 330;
13
const double eps = 1e-8;
14
const double pi = acos( -1.0 );
15
const double inf = 1e20;
16
struct line
17![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
18
point a, b;
19![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
line( )
{ }
20![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
line( point u, point v ) : a( u ), b( v )
{ }
21
};
22![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
23
point p[maxn<<1];
24
line l[maxn];
25![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
26![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
double operator ^( point p1, point p2 )
{ return imag( conj(p1) * p2 ); }
27![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
double operator &( point p1, point p2 )
{ return real( conj(p1) * p2 ); }
28![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
int dblcmp( double x )
{ return ( x < -eps ? -1 : x > eps ); }
29![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
30
bool same( point p1, point p2 )
31![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
32
if( dblcmp( real(p1)- real(p2) ) == 0 && dblcmp( imag(p1) - imag(p2) ) == 0 )
33
return true;
34
return false;
35
}
36
// 判断线段l1是否与直线l2相交
37
bool segcross( line l1, line l2 )
38![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
39
if( dblcmp( l1.a - l2.a ^ l2.b - l2.a ) *
40
dblcmp( l2.b - l2.a ^ l1.b - l2.a ) >= 0 )
41
return true;
42
return false;
43
}
44![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
45
bool check( point p1, point p2, int n )
46![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
47
line l0 = line( p1, p2 );
48
for( int k = 0; k < n; k++ )
49
if( !segcross( l[k], l0 ) ) return false;
50
return true;
51
}
52![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
53
bool solve( int n )
54![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
55
int len = n << 1;
56
int cnt = 0;
57
for( int i = 0; i < len; i++ )
58![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
59
for( int j = i + 1; j < len; j++ )
60![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
61
if( same( p[i], p[j] ) )
62![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
63
cnt++;
64
continue;
65
}
66
if( check( p[i], p[j], n ) )
67
return true;
68
}
69
}
70
if( cnt == len * ( len - 1 ) / 2 ) return true;
71
return false;
72
}
73![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
74
int main( )
75![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
76
int t, n;
77
double x1, x2, y1, y2;
78
//freopen("1005.in","r",stdin);
79
//freopen("out.txt","w",stdout);
80
scanf("%d",&t);
81
while( t-- )
82![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
83
scanf("%d",&n);
84
int len = 0;
85
for( int i = 0; i < n; i++ )
86![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
87
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
88
p[len++] = point( x1, y1 );
89
p[len++] = point( x2, y2 );
90
l[i] = line( p[len-2], p[len-1] );
91
}
92
if( solve( n ) ) printf("Yes\n");
93
else printf("No\n");
94
}
95
return 0;
96
}
97![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)