题意:
给出n条线段,判断是否存在有一条直线,满足所有的线段在直线上投影后至少有一个公共点
等价于:给出n条线段,问你是否存在一条直线,使得每个线段与该直线至少有一个交点。
题解:
嗯,猜测直线一定过至少两个端点。
若不过某线段端点,则可以通过平应找到过一个端点的位置
若过一个端点,则可以旋转使其通过两个端点
暴力枚举端点,判线段直线相交即可~
细节好多,被坑了。。。
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 #include <cmath> 7 8 #define N 1000 9 10 using namespace std; 11 12 double sx[N],sy[N],tx[N],ty[N]; 13 int n,cas; 14 15 inline void read() 16 { 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++) 19 scanf("%lf%lf%lf%lf",&sx[i],&sy[i],&tx[i],&ty[i]); 20 } 21 22 inline int cross(double ax,double ay,double bx,double by) 23 { 24 double sb=ax*by-ay*bx; 25 if(sb>1e-8) return 1; 26 else if(sb<-1e-8) return -1; 27 else return 0; 28 } 29 30 inline int getdis(double ax,double ay,double bx,double by) 31 { 32 double sb=sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by)); 33 if(sb>1e-8) return 1; 34 else if(sb<-1e-8) return -1; 35 else return 0; 36 } 37 38 inline bool check(double ax,double ay,double bx,double by) 39 { 40 if(getdis(ax,ay,bx,by)==0) return 0;//细节!避免两线段共点! 41 for(int i=1;i<=n;i++) 42 { 43 int ans=cross(bx-ax,by-ay,sx[i]-ax,sy[i]-ay)*cross(bx-ax,by-ay,tx[i]-ax,ty[i]-ay); 44 if(ans>0) return false; 45 } 46 return true; 47 } 48 49 inline void go() 50 { 51 if(n==1) {puts("Yes!");return;} 52 for(int i=1;i<=n;i++) 53 for(int j=i+1;j<=n;j++) 54 { 55 if(check(sx[i],sy[i],sx[j],sy[j])) {puts("Yes!"); return;} 56 if(check(sx[i],sy[i],tx[j],ty[j])) {puts("Yes!"); return;} 57 if(check(sx[j],sy[j],tx[i],ty[i])) {puts("Yes!"); return;} 58 if(check(tx[j],ty[j],tx[i],ty[i])) {puts("Yes!"); return;} 59 } 60 puts("No!"); 61 } 62 63 int main() 64 { 65 scanf("%d",&cas); 66 while(cas--) read(),go(); 67 return 0; 68 }