POJ 3304 Segments
蒻苣:弱弱很弱,路过的巨巨还不吝赐教!^.^...QAQ
题意:大概的意思就是,给n条线段,判断是否存在那么一条直线,能够使得每个线段的到直线上的投影至少存在一个公共点。
题解:问题可以转化为:存在一条直线,可以与所有线段相交。
证明:必要条件是所有线段投影的公共部分的垂线必定与所有线段相交。
充分条件是如果有一条直线过所有的线段,则存在一条直线与其垂直。
然后再进一步转化:把这条直线稍微旋转,则必定会过这些线段的某两点。
最后做法就是:枚举每两个点,构成直线,判断是否存在这么两个点构成的直线 能够与所有线段相交。
注意:n==1||n==2可以特判一下,然后,重点:距离 <1E-8即可看作重点( 重点是不能算做两个点的 )
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 #define xo 1e-8 8 struct POINT{ 9 double x,y; 10 POINT(double a = 0, double b = 0) { x = a; y = b; } 11 }; 12 struct LINESEG{ 13 POINT s; 14 POINT e; 15 LINESEG( POINT a, POINT b ) { s = a; e = b; } 16 LINESEG(){} 17 }; 18 LINESEG L[100+5]; 19 double multiply(POINT sp, POINT ep,POINT op) 20 { 21 return ( ( sp.x - op.x )*( ep.y - op.y ) - ( sp.y - op.y )*( ep.x - op.x ) ); 22 } 23 double dist( POINT p1, POINT p2 ) 24 { 25 return (sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y))); 26 } 27 bool pdd(POINT x, POINT y,int n) 28 { 29 if(dist(x,y)<xo) return 0; 30 for(int k = 0;k < n;k++) 31 { 32 double xx = multiply( x , L[k].e , y ); 33 double yy = multiply( x , L[k].s , y ); 34 if(xx*yy>0) return 0; 35 } 36 return 1; 37 } 38 int main() 39 { 40 int test; 41 cin>>test; 42 while(test--) 43 { 44 int n; 45 cin>>n; 46 for(int i = 0; i < n; i++ ) 47 cin>>L[i].e.x>>L[i].e.y>>L[i].s.x>>L[i].s.y; 48 if(n==1){ printf("Yes!\n");continue; } 49 if(n==2) { printf("Yes!\n");continue; } 50 int pos=0; 51 for(int i = 0;i < n; i++) 52 { 53 for(int j = 0;j < n;j++) 54 { 55 POINT x = L[i].e; 56 POINT y = L[j].s; 57 bool pd; 58 pd = pdd(x,y,n); 59 if(pd==1){ 60 printf("Yes!\n");pos = 1;break;} 61 pd = pdd(L[i].e,L[j].e,n); 62 if(pd==1){ 63 printf("Yes!\n");pos = 1;break;} 64 pd = pdd(L[i].s,L[j].s,n); 65 if(pd==1){ 66 printf("Yes!\n");pos = 1;break;} 67 } 68 if(pos) break; 69 } 70 if(!pos) printf("No!\n"); 71 } 72 }
浙公网安备 33010602011771号