POJ 3304 Segments 线段和直线的交点

C - Segments

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d
& %I64u

Submit Status Practice POJ
3304

Appoint description: 
System Crawler  (2016-05-07)

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 on it, all projected segments have at least one point in common.

Input

Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing a positive integer n ≤ 100 showing the number of segments. After that, n lines containing
four real numbers x1y1x2y2 follow, in which (x1y1) and (x2y2) are the coordinates of the two
endpoints for one of the segments.

Output

For each test case, your program must output "Yes!", if a line with desired property exists and must output "No!" otherwise. You must assume that two floating point numbers a and b are equal if |a - b| < 10-8.

Sample Input

3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0

Sample Output

Yes!
Yes!

No!

题意

给你n个线段问是否存在一条直线使得这些线段在这条直线上的投影相交于一点

利用投影的特性就可以知道过这点做垂线必定能与所有的线段相交

那么就转化成了是否存在一条直线和所有线段都相交

如何寻找这条直线呢?

一条直线和线段相交有规范相交和非规范相交

规范相交是指线段的两个端点在直线的两侧

非规范相交是指线段的两个段点至少有一个在直线上

那么对于这道题我们可以把垂线旋转到一定角度一定会出现2条线段与之非规范相交

即过二个线段的端点,那么我们只要枚举任意两个端点就行了

ACcode:
#include <cstdio>
#include <cmath>
#define maxn 200
#define eps 1e-8
int n;
int sgn(double x){
    if(fabs(x)<eps)return 0;
    if(x<0)return -1;
    return 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 operator ^(const Point &b)const{
        return x*b.y-y*b.x;
    }
    double operator *(const Point &b)const{
        return x*b.x+y*b.y;
    }
};
struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e){
        s=_s;
        e=_e;
    }
    int linecrossing(Line v){
        int d1=sgn((e-s)^(v.s-s));
        int d2=sgn((e-s)^(v.e-s));
        if((d1^d2)==-2)return 2;
        return (d1==0||d2==0);
    }
}my[maxn];
double dist(Point a,Point b){
    return sqrt( (b - a)*(b - a) );
}
bool ju(Line tmp){
    if(sgn(dist(tmp.s,tmp.e))==0)return false;
    for(int i=1;i<=n;++i)
        if(tmp.linecrossing(my[i])==0)
            return false;
    return true;
}
int main(){
    int loop;
    scanf("%d",&loop);
    while(loop--){
        double x1,x2,y1,y2;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            my[i]=Line(Point(x1,y1),Point(x2,y2));
        }
        bool flag=true;
        for(int i=1;flag&&i<=n;++i)
            for(int j=1;flag&&j<=n;++j)
                if(ju(Line(my[i].s,my[i].e))||ju(Line(my[i].s,my[j].e))||ju(Line(my[j].s,my[i].s))||ju(Line(my[i].e,my[j].e)))
                    flag=false;
        printf("%s!\n",!flag?"Yes":"No");
    }
    return 0;
}

时间: 2024-10-12 15:13:34

POJ 3304 Segments 线段和直线的交点的相关文章

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

POJ 3304 Segments(判断直线与线段是否相交)

http://poj.org/problem?id=3304 等价于是否存在一条直线穿过所有线段 判断直线与线段是否相交: 首先用两点p1,p2确定了一条直线 在用p1,p2分别与计算线段两个端点计算叉乘即可 ,叉乘之积>0就说明线段两端点在直线的同侧,也就是直线不经过此线段 注意顺序不要搞反了 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #incl

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

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

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.

POJ 3304 Segments 基础线段交判断

LINK 题意:询问是否存在直线,使得所有线段在其上的投影拥有公共点 思路:如果投影拥有公共区域,那么从投影的公共区域作垂线,显然能够与所有线段相交,那么题目转换为询问是否存在直线与所有线段相交.判断相交先求叉积再用跨立定理.枚举每个线段的起始结束点作为直线起点终点遍历即可. /** @Date : 2017-07-12 14:35:44 * @FileName: POJ 3304 基础线段交判断.cpp * @Platform: Windows * @Author : Lweleth ([em

POJ 3304 Segments【叉积】

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

POJ 3304 Segments --枚举,几何

题意: 给n条线段,问有没有一条直线,是每条线段到这条直线上的投影有一个公共点. 解法: 有公共点说明有一条这条直线的垂线过所有线段,要找一条直线过所有线段,等价于从所有线段中任选两端点形成的直线存在可以穿过所有的线段的直线(可将A平移至一条线段端点,然后绕这点旋转,使A过另一条线段端点),然后O(n^2)的枚举找任意两个线段的两个端点,还要找自己这条线段的两个端点,形成一条直线 代码: #include <iostream> #include <cstdio> #include

POJ 3304 Segments[直线与线段相交]

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

POJ 3304 Segments 【计算几何】【直线和线段的关系】

题目链接:http://poj.org/problem?id=3304 题目大意:T个case,每个case里面有N条线段,判断能否存在一条直线,使得所有的线段在这条直线上都能有公共点,如果存在输出Yes,否则输出No. 题目的意思可以变成,在N条直线的2*N个端点中选择两个点组成一条直线能否满足这个条件,暴力枚举即可,注意的一点是在枚举的2*n个点中每次选择的两个点要判断是不是重复的. #include<iostream> #include<stdio.h> #include&l