poj3304Segments+计算几何(二维几何模板)

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 x1 y1 x2 y2 follow, in which (x1, y1) and (x2, y2) 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条线段问是否存在一条直线与每条直线都相交。
解法:自己画了个图,大概看了看,我感觉。。如果这样的直线存在,那么他应该是经过某两条线段的某两个端点的直线。。。敲了一敲,握草啊,直接1A啊,然后又去看了看网上的题解,,大概都是这么做的。。
顺便把直接的二维模板也贴上吧。。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<set>
#define e exp(1.0); //2.718281828
#define mod 1000000007
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
typedef long long LL;
using namespace std;

const double eps=1e-8;
const double pi=acos(-1.0);

int cmp(double x){
    if(fabs(x)<eps) return 0;
    if(x>0) return 1;
    return -1;
}
inline double sqr(double x){
    return x*x;
}
struct point{
    double x,y;
    point(){};
    point(double a,double b):x(a),y(b){};
    void input(){
        scanf("%lf %lf",&x,&y);
    }
    friend point operator + (const point &a,const point &b){
        return point(a.x+b.x,a.y+b.y);
    }
    friend point operator - (const point &a,const point &b){
        return point(a.x-b.x,a.y-b.y);
    }
    friend bool operator == (const point &a,const point &b){
        return cmp(a.x-b.x)==0&&cmp(a.y-b.y)==0;
    }
    friend point operator * (const point &a,const double &b){
        return point(a.x*b,a.y*b);
    }
    friend point operator * (const double &a,const point &b){
        return point(a*b.x,a*b.y);
    }
    friend point operator / (const point &a,const double &b){
        return point(a.x/b,a.y/b);
    }
    double norm(){
        return sqrt(sqr(x)+sqr(y));
    }
};
//计算两个向量的叉积
double det(const point &a,const point &b){
    return a.x*b.y-a.y*b.x;
}
//计算两个点的点积
double dot(const point &a,const point &b){
    return a.x*b.x+a.y*b.y;
}
//计算两个点的距离
double dist(const point &a,const point &b){
    return (a-b).norm();
}
//op沿远点逆时针旋转角度A
point rotate_point(const point &p,double A){
    double tx=p.x,ty=p.y;
    return point(tx*cos(A)-ty*sin(A),tx*sin(A)+ty*cos(A));
}
//判断数k的符号 -1负数 1正数 0零
int dcmp(double k){
    return k<-eps?-1:k>eps?1:0;
}
double cross(const point &a,const point &b){
    return a.x*b.y-a.y*b.x;
}
double abs(const point &o){
    return sqrt(dot(o,o));
}

struct line{
    point a,b;
    line(){};
    line(point x,point y):a(x),b(y){};
};
//两个点生成一个线段/直线
line point_make_pair(const point a,const point b){
    return line(a,b);
}
//p点到线段st的距离
double dis_point_segment(const point p,const point s,const point t){
    if(cmp(dot(p-s,t-s))<0) return (p-s).norm();
    if(cmp(dot(p-t,s-t))<0) return (p-t).norm();
    return fabs(det(s-p,t-p)/dist(t-s,t-s));
}
//p点到线段st的垂足,保存在cp里
void PointProjLine(const point p,const point s,const point t,point &cp){
    double r=dot((t-s),(p-s))/dot(t-s,t-s);
    cp=s+r*(t-s);
}
//判断p点是否在线段st上(包括端点)
bool PointOnSegment(point p,point s,point t){
    return cmp(det(p-s,t-s))==0 && cmp(dot(p-s,p-t))<=0;
}
//判断线段a,b是否平行
bool parallel(line a,line b){
    return !cmp(det(a.a-a.b,b.a-b.b));
}
//判断a,b是否相交,交点保存在res
bool line_make_point(line a,line b,point &res){
    if(parallel(a,b)) return false;
    double s1=det(a.a-b.a,b.b-b.a);
    double s2=det(a.b-b.a,b.b-b.a);
    res=(s1*a.b-s2*a.a)/(s1-s2);
    return true;
}
//将线段a沿法向量平移len的线段
line move_d(line a,const double &len){
    point d=a.b-a.a;
    d=d/d.norm();
    d=rotate_point(d,pi/2);
    return line(a.a+d*len,a.b+d*len);
}
//p0p1 X p0p2
double xmult(point p0,point p1,point p2) {
    return det((p1-p0),(p2-p0));
}
//判断直线l1和线段l2是否相交
bool Seg_inter_line(line l1,line l2) {
    return cmp(xmult(l2.a,l1.a,l1.b))*cmp(xmult(l2.b,l1.a,l1.b)) <= 0;
}

const int maxn=1000;
struct polygon{
    int n;
    point a[maxn];
    polygon(){};
//多边形的周长
    double perimeter(){
        double sum=0;
        a[n]=a[0];
        for(int i=0;i<n;i++) sum+=(a[i+1]-a[i]).norm();
        return sum;
    }
//多边形的面积
    double area(){
        double sum=0;
        a[n]=a[0];
        for(int i=0;i<n;i++) sum+=det(a[i+1],a[i]);
        return sum/2;
    }
//判断点是否在多边形内,0多边形外,1多边形内,2边界上
    int Point_In(point t){
        int num=0;
        a[n]=a[0];
        for(int i=0;i<n;i++){
            if(PointOnSegment(t,a[i],a[i+1])) return 2;
            int k=cmp(det(a[i+1]-a[i],t-a[i]));
            int d1=cmp(a[i].y-t.y);
            int d2=cmp(a[i+1].y-t.y);
            if(k>0&&d1<=0&&d2>0) num++;
            if(k<0&&d2<=0&&d1>0) num--;
        }
        return num!=0;
    }
};

struct Circle{
    point p;
    double r;
    bool operator < (const Circle &o) const{
        if(dcmp(r-o.r)!=0) return dcmp(r-o.r)==-1;
        if(dcmp(p.x-o.p.x)!=0){
            return dcmp(p.x-o.p.x)==-1;
        }
        return dcmp(p.y-o.p.y)==-1;
    }
    bool operator == (const Circle &o) const{
        return dcmp(r-o.r)==0&&dcmp(p.x-o.p.x)==0&&dcmp(p.y-o.p.y)==0;
    }
};

/*************************************/


line x[110];
bool check(line a,int n){
    if(cmp(dist(a.a,a.b))==0) return false;
    for(int i=0;i<n;i++){
        if(Seg_inter_line(a,x[i])==false) return false;
    }
    return true;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%lf %lf %lf %lf",&x[i].a.x,&x[i].a.y,&x[i].b.x,&x[i].b.y);

        bool flag=false;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(check(point_make_pair(x[i].a,x[j].a),n)==true) flag=true;
                if(check(point_make_pair(x[i].a,x[j].b),n)==true) flag=true;
                if(check(point_make_pair(x[i].b,x[j].a),n)==true) flag=true;
                if(check(point_make_pair(x[i].b,x[j].b),n)==true) flag=true;
                if(flag) break;
            }
            if(flag) break;
        }
        if(flag) printf("Yes!\n");
        else printf("No!\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值