码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2826 题解

时间:2017-06-23 15:37:26      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:size   lin   log   math   print   poj   line   线段   bsp   

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

技术分享

 

题解:基本思路是求出两条线段交点,然后计算在交点上方部分三角形(短板效应,大小由较小的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\n");
            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\n");
            continue;
        }
        if (l1>=l2) h1=l2*h1/l1;
            else h2=l1*h2/l2;
        printf("%.2f\n",abs(det(h1,h2)/2));
    }
    return 0;
}

 

poj 2826 题解

标签:size   lin   log   math   print   poj   line   线段   bsp   

原文地址:http://www.cnblogs.com/terra/p/7069595.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!