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<math.h>
#include<cstring>
#include<stdlib.h>
using namespace std;

#define eps 1e-8
#define zero(x) (((x)>0? (x):-(x))<eps) //是0则返回1,否则返回0
#define _sign(x) ((x)>eps? 1:((x)<-eps? 2:0))//负数 0 正数 分别返回 2 0 1

struct point {
    double x;double y;
    point(const double &x = 0, const double &y = 0):x(x), y(y){}
    void in(){  scanf("%lf %lf", &x, &y); }
    void out()const{ printf("%.2f %.2f\n",x, y);}
};
struct line  {
    point a,b;
    line(const point &a = point(), const point &b = point()):a(a), b(b){}
    void in(){ a.in(); b.in();}
    void out()const{ a.out(); b.out(); }
};
//计算叉乘(P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){  //p0是中间
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

//判两点在直线同侧,是的话返回1
int same_side(point p1,point p2,line l){
	return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;
}

line L[105];
point P[500];
int N;
int judge(line LL){
    if( _sign(LL.a.x-LL.b.x)==0 && _sign(LL.a.y-LL.b.y)==0 ) return 0;
    for(int i=0;i<N;i++){
        if(same_side(L[i].a,L[i].b,LL)==1) return 0;
    }
    return 1;
}

int main ()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        for(int i=0;i<N*2;i++) P[i].in();
        for(int i=0;i<N;i++){
            L[i].a=P[i*2];
            L[i].b=P[i*2+1];
        }
        int flag = 0;
        for(int i=0;i<N*2-1;i++)
        for(int j=i+1;j<N*2;j++){
            line LL;
            LL.a=P[i];
            LL.b=P[j];
            if(judge(LL)==1) {flag=1;break;}
        }
        if(flag==1) cout<<"Yes!"<<endl;
        else cout<<"No!"<<endl;
    }
}
时间: 2024-11-06 01:37:26

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

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

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

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

题目链接 题意 : 能否找出一条直线使得所有给定的线段在该直线上的投影有一个公共点. 思路 : 假设存在一条直线a使得所有线段在该直线上的投影有公共点,则必存在一条垂直于直线a的直线b,直线b与所有线段相交,所以问题又转变为是否存在一条直线与所在所有线段相交. 假设这样的直线存在,则这一条直线可能与某一条或者某些线段的端点重合,也可能不重合.对于那些没有在端点相交的线段,我们可以把这一条直线通过旋转或平移,让其先与一条线段在线段的端点相交(那此时这一条直线与别的线段就在别的线段的中间相交), 然

POJ 3304 Segments(计算几何)

题意:给定一些线段,问能否找出一条直线,穿过所有线段 思路:如果存在一条直线,那么必然有一条直线是过已有的两点,那么就枚举两点,然后去判断是否跟所有线段有交点即可 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; struct Point { double x, y; Point() {} Point(doub

poj 2318 TOYS(计算几何 点与线段的关系)

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12015   Accepted: 5792 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w

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 线段和直线的交点

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, w

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 基础线段交判断

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

[POJ 3304]Segments

Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14918   Accepted: 4728 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 叉积

题意: 找出一条直线,让给出的n条线段在这条直线的投影至少有一个重合的点 转化一下,以重合的点作垂线,那么这条直线一定经过那n条线段.现在就是求找到一条直线,让这条直线经过所有线段 分析: 假设存在这一条直线,我们以无穷远处作为支点,然后旋转,直到碰到一个线段的端点就停止旋转,此时还是穿过了所有线段: 然后以这个端点为支点,旋转直线,直到碰到一个线段的端点就停止旋转,此时也穿过了所有线段. 于是就证明了,如果直线与所有线段相交,那么必定存在一条直线经过线段中的两个端点 那么,接下来枚举即可.注意