POJ 3304 计算几何 直线与线段相交

题意:

给出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 }

 

 

你可能感兴趣的:(poj)