poj2826(细节,计算几何)

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

题意:平面中摆两根木棍,雨水从上垂直下落,问木棍中能乘多少水。

思路:

  细节很多,坑QAQ。。

  首先不相交时肯定为0.00,然后其中有一条木棍是水平的也不行,最后是如果开口被堵住了也不行(通过判断其中一根木棍l1的上端点向上引射线是否与l2相交)。

   最后输出答案时需要加上eps,因为会出现-0.0和0.0的情况,不然会wa到你哭!double的精度就是迷,我也想不通-0.0是怎么出现的,算是经验了,以后碰到输出double的情况注意下-0.0。

AC code:

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

const double eps=1e-8;
const double inf=1e20;

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

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;
    }
    //绕原点旋转角度b(弧度值),后x、y的变化
    void transXY(double b){
        double tx=x,ty=y;
        x=tx*cos(b)-ty*sin(b);
        y=tx*sin(b)+ty*cos(b);
    }
};

struct Line{
    Point s,e;
    Line(){}
    Line(Point ss,Point ee){
        s=ss,e=ee;
    }
    //两直线相交求交点
    //第一个值为0表示直线重合,为1表示平行,为2表示相交
    //只有第一个值为2时,交点才有意义
    pair<int,Point> operator &(const Line &b)const{
        Point res = s;
        if(sgn((s-e)^(b.s-b.e)) == 0)
        {
            if(sgn((s-b.e)^(b.s-b.e)) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x += (e.x-s.x)*t;
        res.y += (e.y-s.y)*t;
        return make_pair(2,res);
    }
};
//判断线段相交
bool inter(Line l1,Line l2){
    return
        max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&
        max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&
        max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&
        max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&
        sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=0&&
        sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=0;
}

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

int T;

int main(){
    scanf("%d",&T);
    double x1,yy1,x2,yy2,x3,yy3,x4,yy4;
    Line l1,l2;
    while(T--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&yy1,&x2,&yy2,&x3,&yy3,&x4,&yy4);
        l1=Line(Point(x1,yy1),Point(x2,yy2));
        l2=Line(Point(x3,yy3),Point(x4,yy4));
        if(!inter(l1,l2)){
            printf("0.00
");
            continue;
        }
        if(sgn(l1.s.y-l1.e.y)==0||sgn(l2.s.y-l2.e.y)==0){
            printf("0.00
");
            continue;
        }
        if(sgn(l1.s.y-l1.e.y)<0) swap(l1.s,l1.e);
        if(sgn(l2.s.y-l2.e.y)<0) swap(l2.s,l2.e);
        if(inter(Line(l1.s,Point(l1.s.x,10005)),l2)||inter(Line(l2.s,Point(l2.s.x,10005)),l1)){
            printf("0.00
");
            continue;
        }
        pair<int,Point> pr=l1&l2;
        Point p=pr.second;
        double ans1,ans2;
        pr=l1&Line(Point(10005,l2.s.y),l2.s);
        Point p1=pr.second;
        ans1=abs((l2.s-p)^(p1-p))/2;
        pr=l2&Line(Point(10005,l1.s.y),l1.s);
        Point p2=pr.second;
        ans2=abs((l1.s-p)^(p2-p))/2;
        printf("%.2f
",eps+min(ans1,ans2));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/FrankChen831X/p/11511423.html