• poj 2826 题解


    题意:给出两条线段的位置(可相交),用它们来接落下来的雨水,问最终储水量是多少

    题解:基本思路是求出两条线段交点,然后计算在交点上方部分三角形(短板效应,大小由较小的y确定)的面积即可。

    注意点:事实上这个问题是判定+计算,要判定能不能接到水,再进行计算。

    判定①:线段不相交或平行,则接不到水

    判定②:以交点为起点的两条向上的两条线段中,一条线段完全挡住了另一条线段,则接不到水

    由于存在判定,所以会出现精度问题,要注意eps的使用

    实现:

    ①每条线段被交点分成两部分,用(1,0)×线段,选取结果大于零的那条,即是在上方的

    ②判断完全挡住的时候,先比较x值(是否同号,以及大小),再用x*det的正负号进行判断(在一,四象限,覆盖时两条线段方向有区别)

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const double eps=1e-9;
    
    struct point{
        double x,y;
        point(){}
        point (double a,double b): x(a),y(b) {}
    
        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 point operator * (const double &r,const point &a){
            return point(r*a.x,r*a.y);
        }
    
        friend point operator / (const point &a,const double &r){
            return point(a.x/r,a.y/r);
        }
    
        double norm(){
            return sqrt(x*x+y*y);
        }
    };
    
    inline double det(point a,point b) {return a.x*b.y-a.y*b.x;}
    
    inline bool line_cross_segment(point s,point t,point a,point b)
    {
        return !(det(s-a,t-a)*det(s-b,t-b)>eps);
    }
    
    inline bool parallel(point a,point b,point c,point d){return abs(det(a-b,c-d))<eps;}
    
    inline bool seg_cross_seg(point a,point b,point c,point d)
    {
        if (min(c.x,d.x)>max(a.x,b.x)+eps || min(a.x,b.x)>max(c.x,d.x)+eps || min(c.y,d.y)>max(a.y,b.y)+eps || min(a.y,b.y)>max(c.y,d.y)+eps)
            return false;
        return det(a-c,d-c)*det(b-c,d-c)<eps && det(c-a,b-a)*det(d-a,b-a)<eps;
    }
    
    inline point line_make_point(point s1,point t1,point s2,point t2) //逻辑上必须先判断parallel
    {
        double a1=det(s1-s2,t2-s2);
        double a2=det(t1-s2,t2-s2);
        return (a1*t1-a2*s1)/(a1-a2);
    }
    
    int n;
    point s1,t1,s2,t2,cr,hx,h1,h2;
    double l1,l2;
    double ans;
    
    inline bool check(point l1,point l2)
    {
        if (l1.x*l2.x<eps) return true;
        if (abs(l1.x)>abs(l2.x)-eps && l1.x*det(l1,l2)<eps) return false;
        if (abs(l2.x)>abs(l1.x)-eps && l2.x*det(l2,l1)<eps) return false;
        return true;
    }
    
    int main()
    {
        scanf("%d",&n);
        while (n--)
        {
            scanf("%lf%lf%lf%lf",&s1.x,&s1.y,&t1.x,&t1.y);
            scanf("%lf%lf%lf%lf",&s2.x,&s2.y,&t2.x,&t2.y);
            if (parallel(s1,t1,s2,t2) || !(seg_cross_seg(s1,t1,s2,t2)))
            {
                printf("0.00
    ");
                continue;
            }
            cr=line_make_point(s1,t1,s2,t2);
            hx=point(1,0);
            if (det(hx,s1-cr)>eps) h1=s1-cr;else h1=t1-cr;
            if (det(hx,s2-cr)>eps) h2=s2-cr;else h2=t2-cr;
            l1=h1.y;l2=h2.y;
            if (l1<eps || l2<eps || !check(h1,h2))
            {
                printf("0.00
    ");
                continue;
            }
            if (l1>=l2) h1=l2*h1/l1;
                else h2=l1*h2/l2;
            printf("%.2f
    ",abs(det(h1,h2)/2));
        }
        return 0;
    }
  • 相关阅读:
    使用springamqp发送消息及同步接收消息
    对未登陆的用户进行处理的页面
    查找某些字符是否在另一个字符串里出现的高效算法
    正则表达式
    华中地区高校第七届ACM程序设计大赛——递增序列【2012年5月27日】
    HDOJ2021 ( 发工资咯:) ) 【水题】
    循环冗余校验(CRC)【C语言 位运算】
    HDOJ2028 ( Lowest Common Multiple Plus ) 【水题,lcm】
    HDOJ2015 ( 偶数求和 ) 【水题】
    HDOJ2027 ( 统计元音 ) 【水题】
  • 原文地址:https://www.cnblogs.com/terra/p/7069595.html
Copyright © 2020-2023  润新知