首页 > 代码库 > HDU 3492 (直线与所有线段相交) Segment

HDU 3492 (直线与所有线段相交) Segment

题意:

给出n个线段,判断是否存在一条直线使得所有线段在直线上的射影的交非空。

分析:

如果我们找到一条与所有线段相交的直线,然后做一条与该直线垂直的直线,这些线段在直线上的射影就一定包含这个垂足。

所以我们只要判断是否存在一条直线与所有的点相交即可。

如果存在这样一条直线,那么将这条直线平移或者旋转,就会被这些线段中的某两个端点“卡”住。

所以我们枚举两个端点,然后判断这些线段是否与这两个点所在的直线都相交即可。

 

本以为是一道很简单的计算几何,结果卡了好几天。

看了别人的题解,才发现问题所在。

http://www.cppblog.com/acronix/archive/2010/08/17/123765.html

因为有可能存在重点,所以要判断,弄了个标志变量issame,如果所有的点都是同一个点那么也应该输出Yes

 1 #include <cstdio> 2 #include <cmath> 3  4 const int maxn = 600 + 10; 5 const double eps = 1e-8; 6 struct Point 7 { 8     double x, y; 9     Point(double x=0, double y=0):x(x), y(y) {}10 }p[maxn];11 int dcmp(double x)12 {13     if(fabs(x) < eps) return 0;14     return x < 0 ? -1 : 1;15 }16 17 Point operator - (const Point& a, const Point& b)18 { return Point(a.x-b.x, a.y-b.y); }19 20 double Cross(const Point& a, const Point& b)21 { return (a.x*b.y - a.y*b.x); }22 23 bool operator == (const Point& a, const Point& b)24 { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; }25 26 bool intersect(const Point& a, const Point& b, const Point& p1, const Point& p2)27 {28     int d1 = dcmp(Cross(b-a, p1-a));29     int d2 = dcmp(Cross(b-a, p2-a));30     if(d1 == 0 || d2 == 0) return true;31     if(d1 * d2 < 0) return true;32     return false;33 }34 35 int main(void)36 {37     //freopen("3492in.txt", "r", stdin);38     int T;39     scanf("%d", &T);40     while(T--)41     {42         int n;43         scanf("%d", &n);44         for(int i = 0; i < 2*n-1; i += 2)45             scanf("%lf%lf%lf%lf", &p[i].x, &p[i].y, &p[i+1].x, &p[i+1].y);46         47         bool exist = false;48         bool issame = true;49         for(int i = 0; i < 2*n-1 && !exist; ++i)50         {51             for(int j = i+1; j < 2*n && !exist; ++j)52             {53                 if(p[i] == p[j]) continue;54                 issame = false;55                 int k;56                 for(k = 0; k < 2*n; k += 2)57                     if(!intersect(p[i], p[j], p[k], p[k+1])) break;58                 if(k == 2 * n)59                     exist = true;60             }61         }62         63         if(exist || issame) puts("Yes");64         else puts("No");65     }66     67     return 0;68 } 
代码君

 

HDU 3492 (直线与所有线段相交) Segment