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 }

 

 

posted @ 2013-01-10 21:24  proverbs  阅读(452)  评论(0编辑  收藏  举报