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 } 

代码君

时间: 2024-10-06 01:19:39

HDU 3492 (直线与所有线段相交) Segment的相关文章

hdu 4606 Occupy Cities(线段相交+最小路径覆盖+二分)

Occupy Cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1178    Accepted Submission(s): 388 Problem Description The Star Wars is coming to an end as the Apple Planet is beaten by the Ban

hdu 1147 Pick-up sticks 判断线段相交 ~~ 注意判断顺序!!不然容易超时

Pick-up sticks Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2216    Accepted Submission(s): 815 Problem Description Stan has n sticks of various length. He throws them one at a time on the f

hdu 1558 (线段相交+并查集) Segment set

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐标,当输入Q的时候输入n,然后输出与第n条线段相交的线段有多少条 首先判断线段是否相交,在算法导论p577上有介绍 线段A(x1,y1)-B(x2,y2),所在直线L1方程为F1(x,y)=0;线段C(x3,y3)-D(x4,y4),所在直线L2方程为F2(x,y)=0; 如何判断两条线段有交点:(

hdu 3304(直线与线段相交)

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12042   Accepted: 3808 Description Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments

HDU1558 - Segment set 并查集 + 判断线段相交

HDU1558 - Segment set: http://acm.hdu.edu.cn/showproblem.php?pid=1558 题目大意: 输入一些线段的端点坐标,若两线段相交,则把他们合并成一个集合,输入数据里会有k,问和k线段相交的线段的数目(包括自己) 思路: 每次输入一条线段,都从头扫描一次. 找出之前输入的线段里面,所有和其相交的线段,并且合并(合并用的是线段的ID). 就是: 并查集 + 判断线段相交 代码: #include <iostream> #include &

poj 3304 直线与线段相交

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12161   Accepted: 3847 Description Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments

HDU 1086 You can Solve a Geometry Problem too(判断线段相交)

题目地址:HDU 1086 就这么一道仅仅判断线段相交的题目写了2k多B的代码..是不是有点浪费...但是我觉得似乎哪里也优化不了了.... 判断线段相交就是利用的叉积.假如现在两条线段分别是L1和L2,先求L1和L2两个端点与L1的某个端点的向量的叉积,如果这两个的叉积的乘积小于0的话,说明L1在是在L2两个端点之间的,但此时并不保证一定相交.此时需要用同样的方法去判断L2是否在L1的两个端点之间,如果L2也在L1的两个端点之间的话,那就足以说明L1与L2相交.但是这题还需要判断是否端点也相交

直线与直线相交 直线与线段相交 线段与线段相交

int sgn(double x) { if(fabs(x) < eps) return 0; return x < 0 ? -1:1; } struct Point { double x,y; Point() {} Point(double _x,double _y) { x = _x,y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉积 double opera

POJ 3304 Segments(计算几何:直线与线段相交)

POJ 3304 Segments 大意:给你一些线段,找出一条直线能够穿过所有的线段,相交包括端点. 思路:遍历所有的端点,取两个点形成直线,判断直线是否与所有线段相交,如果存在这样的直线,输出Yes,但是注意去重. struct Point { double x, y; } P[210]; struct Line { Point a, b; } L[110]; double xmult(Point p1, Point p2, Point p) { return (p1.x-p.x)*(p2.