poj3304(叉积判断直线和线段相交)

时间:2019-09-06
本文章向大家介绍poj3304(叉积判断直线和线段相交),主要包括poj3304(叉积判断直线和线段相交)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目链接:https://vjudge.net/problem/POJ-3304

题意:求是否能找到一条直线,使得n条线段在该直线的投影有公共点。

思路:

  如果存在这样的直线,那么在公共投影点作直线的垂线,显然该垂线会经过所有直线,那么原题转换为求是否有经过所有线段的直线。

  如果存在这样的直线,那么该直线一定能通过平移和旋转之后经过所有线段中的两个端点,那么我们枚举所有两两线段的端点作为直线的两点,然后是判断直线是否经过所有线段。如果线段为p0p1,直线为p2p3,那么相交时满足:(p0p2^p0p3)*(p1p2^p1p3)<=0。总复杂度为O(n^3)。

AC code:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;

const int maxn=105;
const double eps=1e-8;
int T,n,flag;

struct Point{
    double x,y;
    Point(){}
    Point(double xx,double yy):x(xx),y(yy){}
    Point operator + (const Point& b)const{
        return Point(x+b.x,y+b.y);
    }
    Point operator - (const Point& b)const{
        return Point(x-b.x,y-b.y);
    }
    double operator * (const Point& b)const{
        return x*b.x+y*b.y;
    }
    double operator ^ (const Point& b)const{
        return x*b.y-b.x*y;
    }
};

struct Line{
    Point s,e;
    Line(){};
    Line(Point ss,Point ee){
        s=ss,e=ee;
    }
}line[maxn];

int sgn(double x){
    if(abs(x)<eps) return 0;
    if(x<0) return -1;
    return 1;
}

double dist(Point a,Point b){
    return sqrt((b-a)*(b-a));
}

double xmult(Point p0,Point p1,Point p2){  //p0p1 ^ p0p2
    return (p1-p0)^(p2-p0);
}

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;
}

bool check(Point p1,Point p2){
    if(sgn(dist(p1,p2))==0) return 0;
    Line l1=Line(p1,p2);
    for(int i=1;i<=n;++i)
        if(!seg_inter_line(l1,line[i]))
            return 0;
    return 1;
}

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

原文地址:https://www.cnblogs.com/FrankChen831X/p/11478029.html