判断线段和直线相交 POJ 3304

 1 // 判断线段和直线相交 POJ 3304
 2 // 思路:
 3 // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交。
 4
 5 #include <cstdio>
 6 #include <cstring>
 7 #include <iostream>
 8 #include <algorithm>
 9 #include <map>
10 #include <set>
11 #include <queue>
12 #include <stdlib.h>
13 #include <cmath>
14 using namespace std;
15 typedef long long LL;
16 const LL inf = 1e18;
17 const int N = 5000;
18 const double eps = 1e-8;
19
20 int sgn(double x){
21     if(fabs(x)<eps) return  0;
22     if(x<0) return -1;
23     return 1;
24 }
25
26 struct Point{
27     double x,y;
28     Point(){}
29     Point(double _x,double _y){
30         x=_x;y=_y;
31     }
32     Point operator -(const Point &b)const{
33         return Point(x-b.x,y-b.y);
34     }
35     double operator *(const Point &b)const{
36         return x*b.x+y*b.y;
37     }
38     double operator ^(const Point &b)const{
39         return x*b.y-y*b.x;
40     }
41 };
42
43 struct Line{
44     Point s,e;
45     Line(){}
46     Line(Point _s,Point _e){
47         s=_s,e=_e;
48     }
49 };
50
51 double xmult(Point p0,Point p1,Point p2){
52     return (p1-p0)^(p2-p0);
53 }
54
55 bool Seg_inter_line(Line l1,Line l2){
56     return sgn(xmult(l2.s,l1.s,l1.e))*sgn(xmult(l2.e,l1.s,l1.e))<=0;
57 }
58
59 double dist(Point a,Point b){
60     return sqrt((a-b)*(a-b));
61 }
62 Line line[N];
63 bool work(Line l1,int n){
64     if(sgn(dist(l1.s,l1.e))==0) return false;
65     for(int i=0;i<n;i++){
66         if(Seg_inter_line(l1,line[i])==false) return false;
67     }
68     return true;
69 }
70 int main(){
71     int n,T;
72     scanf("%d",&T);
73     while(T--){
74         scanf("%d",&n);
75         double x1,y1,x2,y2;
76         for(int i=0;i<n;i++){
77             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
78             line[i]=Line(Point(x1,y1),Point(x2,y2));
79         }
80         bool flag=false;
81         for(int i=0;i<n;i++){
82             for(int j=0;j<n;j++){
83                 if(work(Line(line[i].s,line[j].e),n)||work(Line(line[i].s,line[j].s),n)||work(Line(line[i].e,line[j].e),n)||work(Line(line[i].e,line[j].s),n)){
84                     flag=true;
85                     break;
86                 }
87             }
88             if(flag) break;
89         }
90         if(flag) puts("Yes!");
91         else puts("No!");
92     }
93     return 0;
94 }
时间: 2024-08-10 17:00:33

判断线段和直线相交 POJ 3304的相关文章

线段和矩形相交 POJ 1410

1 // 线段和矩形相交 POJ 1410 2 3 // #include <bits/stdc++.h> 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <algorithm> 8 #include <vector> 9 #include <math.h> 10 using namespace std; 11 #defin

直线相交 POJ 1269

1 // 直线相交 POJ 1269 2 3 // #include <bits/stdc++.h> 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <algorithm> 8 #include <math.h> 9 using namespace std; 10 #define LL long long 11 typedef pair

POJ 3304 Segments (线段和直线相交 + 思维)

题目:传送门 题意: 给你n条线段的两个端点,问所有线段投影到一条直线上,这些投影至少相交于一点,就输出Yes!,否则就是 No! 题解:  戳 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include &

poj 1410 Intersection (判断线段与矩形相交 判线段相交)

题目链接 Intersection Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12040   Accepted: 3125 Description You are to write a program that has to decide whether a given line segment intersects a given rectangle. An example: line: start point:

POJ 3304 segments 线段和直线相交

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14178   Accepted: 4521 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

POJ1912 A highway and the seven dwarfs (判断凸包与直线相交 logn)

POJ1912 给定n个点 和若干条直线,判断对于一条直线,是否存在两个点在直线的两侧. 显然原命题等价于 凸包与直线是否相交. O(n)的算法是显而易见的 但是直线数量太多 就会复杂到O(n^2)由于n<=100000 会TLE 凸包有个很好的性质,我们没有利用, 那就是凸包的边相对于要判断的直线是极角有序的! 于是得到算法: 构造好凸包后,二分找凸包上第一个与正向直线夹角大于0的线段和第一个与反向直线夹角大于0的线段 然后判断两线段的起点是否在直线两侧即可. 代码实现有一点注意的细节:不要用

[poj] 1066 Treasure Hunt || 判断直线相交

原题 在金字塔内有一个宝藏p(x,y),现在要取出这个宝藏. 在金字塔内有许多墙,为了进入宝藏所在的房间必须把墙炸开,但是炸墙只能炸每个房间墙的中点. 求将宝藏运出城堡所需要的最小炸墙数. 判断点和直线相交. 枚举每道墙的两个端点和p的连线这条线段和墙的交点的次数最小值即为需要炸墙的最小次数. [注意当墙数为零时输出1:] #include<cstdio> #include<algorithm> #define N 33 using namespace std; int ans=0

POJ 3304 Segments【叉积】

题意:有n条线段,问有没有一条直线使得所有线段在这条直线上的投影至少有一个共同点. 思路:逆向思维,很明显这个问题可以转化为是否有一条直线穿过所有线段,若有,问题要求的直线与该直线垂直,并且公共点为垂足. 因此只需要枚举每两个端点形成的直线,判断是否和所有线段相交.证明,若存在一条与所有线段相交的直线L,则可以将L平移直到再移动就不满足"与所有线段相交"这个条件时,此时L经过某个线段的一个端点,再将L旋转直到再旋转就不满足“与所有线段相交"这个条件时,肯定与另一个端点相交.

POJ 3304 Segments 判断直线和线段相交

POJ 3304  Segments 题意:给定n(n<=100)条线段,问你是否存在这样的一条直线,使得所有线段投影下去后,至少都有一个交点. 思路:对于投影在所求直线上面的相交阴影,我们可以在那里作一条线,那么这条线就和所有线段都至少有一个交点,所以如果有一条直线和所有线段都有交点的话,那么就一定有解. 怎么确定有没直线和所有线段都相交?怎么枚举这样的直线?思路就是固定两个点,这两个点在所有线段上任意取就可以,然后以这两个点作为直线,去判断其他线段即可.为什么呢?因为如果有直线和所有线段都相