线段判交——poj2826

目前poj似乎数据出了问题,拿以前a的代码交上去也是wa

总体来说,要考虑三种答案0.00的情况

  1.线段不相交

  2.一根线段水平

  3.开口被封闭,即高的那一端把低的那一端完全遮住了

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;}
int cmp(db k1,db k2){return sign(k1-k2);}

struct point{
    db x,y;
    point(){}
    point(db x,db y):x(x),y(y){}
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
};
struct line{
    point p[2];
};

db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
int intersect(db l1,db r1,db l2,db r2){
    if(l1>r1)swap(l1,r1);if(l2>r2)swap(l2,r2);
    return cmp(r1,l2)!=-1 && cmp(r2,l1)!=-1;
}
int checkSS(point k1,point k2,point k3,point k4){
    return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
    sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0 &&
    sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
}
point getLL(point k1,point k2,point k3,point k4){
    db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3);
    return (k1*w2+k2*w1)/(w1+w2);
}
point p[10],k1,k2,k3,k4,k5,k6,k7;
line l1,l2,l3;

int main(){
    int t;cin>>t;
    while(t--){
        scanf("%lf%lf",&k1.x,&k1.y);
        scanf("%lf%lf",&k2.x,&k2.y);
        scanf("%lf%lf",&k3.x,&k3.y);
        scanf("%lf%lf",&k4.x,&k4.y);
        l1.p[0]=k1;l1.p[1]=k2;
        l1.p[0]=k3;l1.p[1]=k4;
        if(checkSS(k1,k2,k3,k4)==0){
            puts("0.00");continue;
        }
        int tot=0;
        k5=getLL(k1,k2,k3,k4);//两线段交点 
        if(k1.y>k5.y)p[++tot]=k1;//找两个比交点高的点 
        if(k2.y>k5.y)p[++tot]=k2;
        if(k3.y>k5.y)p[++tot]=k3;
        if(k4.y>k5.y)p[++tot]=k4;
        if(tot!=2){
            puts("0.00");continue;
        }
        
        if(p[1].y>p[2].y)swap(p[1],p[2]);
        
        //判封闭,从p1用一根直线向上 
        point tmp=p[1];tmp.y+=100000;
            if(checkSS(p[1],tmp,k5,p[2])){
            point k8=getLL(p[1],tmp,k5,p[2]);
            if(k8.y>p[1].y){
                puts("0.00");continue;
            } 
        }
        
        //求面积,从p1用一根直线横向延伸 
        k6=p[1];k6.x++;
        k7=getLL(k6,p[1],k5,p[2]);
        db area=0.5*(k6.y-k5.y)*fabs(k7.x-p[1].x);
        printf("%.2f\n",area);
    }
}
/*
9
6259 2664 8292 9080 1244 2972 9097 9680
0 1 1 0
1 0 2 1
0 1 2 1
1 0 1 2
0 0 10 10
0 0 9 8
0 0 10 10
0 0 8 9
0.9 3.1 4 0
0 3 2 2
0 0 0 2
0 0 -3 2
1 1 1 4
0 0 2 3
1 2 1 4
0 0 2 3

*/

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12327687.html
今日推荐