您的位置:首页 > 其它

poj 3304 Segments(判断线段和直线相交)

2014-09-05 19:42 405 查看
题目链接:点击打开链接

题意:给出一些线段,判断是否存在一条直线,使所有线段在这条直线上的投影都有公共部分(project是投影的意思)

如果有公共部分,那么做这公共部分的垂线一定经过所有线段,本题数据量只有100,所以可以枚举任意两个端点看是否穿过所有线段。

判断线段相交可以参考这里:判断线段相交

本题是判断线段和直线相交,所以当叉积等于0时就可以确定端点在直线上,但如果是线段就不行,还需判断端点是否在线段上,因为可能在线段延长线上。

枚举两端点时需要注意要判断两端点是否重合,如果重合,对于一个点所有的线段算叉积一定等于0,WA了几次。

代码:

#include <iostream>
using namespace std;
#include <cstdio>
#include <cstring>
#define eps 1e-8
int n,len;
struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator - (Point obj){
        return Point(x-obj.x,y-obj.y);
    }
}P[300];

double fabs(double n){
    return n>0?n:-n;
}

struct seg{
    Point a,b;
}S[105];

double Cross(Point a,Point b){
    return a.x*b.y-b.x*a.y;
}

double Dot(Point a,Point b){
    return a.x*b.x+a.y*b.y;
}
int dcmp(double a){
    if(fabs(a)<eps) return 0;
    return a>0?1:-1;
}
bool Seginter(Point a,Point b,Point c,Point d){
    double t1=Cross(a-d,c-d);
    double t2=Cross(b-d,c-d);

    return (dcmp(t1)*dcmp(t2)<=0);
}

bool solve(){
    for(int i=1;i<=len;i++){
        for(int j=i+1;j<=len;j++){
            if(!dcmp(P[i].x-P[j].x)&&!dcmp(P[i].y-P[j].y))continue;
            for(int k=1;k<=n;k++){
            if(!Seginter(S[k].a,S[k].b,P[i],P[j])) break;
            if(k==n) return 1;
            }
        }
    }
    return 0;
}

void init(){
    int pnum=0;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf%lf",&S[i].a.x,&S[i].a.y,&S[i].b.x,&S[i].b.y);
        P[++pnum]=S[i].a;
        P[++pnum]=S[i].b;
    }
    len=pnum;
}

int main(){
    int T;
    cin>>T;
    while(T--){
        scanf("%d",&n);
        init();
        if(solve()) printf("Yes!\n");
        else printf("No!\n");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: