[poj3304]Segments

题目大意:转化为是否存在一条直线可以穿过所有的线段。

解题关键:线段与直线相交的判断,模板题。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
typedef long long ll;
using namespace std;
const double eps=1e-8;
int n,T;
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;}
};
double xmult(Point p0,Point p1,Point p2){return (p1-p0)^(p2-p0);}
int sgn(double x){
    if(fabs(x)<eps)return 0;
    if(x<0) return -1;
    return 1;
}

bool Seg_inter_line(Line l1,Line l2){//判断直线l1和线段l2是否相交,重点;懂了 
    return sgn(xmult(l2.s,l1.s,l1.e))*sgn(xmult(l2.e,l1.s,l1.e))<=0;
}

double dist(Point a,Point b){return sqrt((b-a)*(b-a));}
const int MAXN=110;
Line line[MAXN];

bool check(Line l1){
    if(sgn(dist(l1.s,l1.e))==0)return false;//判断重合点 
    for(int i=0;i<n;i++)
        if(Seg_inter_line(l1,line[i])==false) return false;
    return true;
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        double x1,y1,x2,y2;
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[i]=Line(Point(x1,y1),Point(x2,y2));
        }
        bool flag=false;
        for(int i=0;i<n;i++)
            for(int j=i;j<n;j++)
                if(check(Line(line[i].s,line[j].s))||check(Line(line[i].s,line[j].e))
                        ||check(Line(line[i].e,line[j].s))||check(Line(line[i].e,line[j].e)) ){
                    flag=true;
                    break;
                }
        if(flag)  printf("Yes!\n");
        else printf("No!\n");
    }
    return 0;
}

 

posted @ 2018-04-06 00:44  Elpsywk  阅读(176)  评论(0编辑  收藏  举报