poj 2826 几何

传送门

题意:平面上两线段,问从上往下掉水,能接多少水。

思路:分类讨论

大致分类:

1、不相交或斜率相等

2、入口被覆盖

3、能接水的情况

自己分析吧,其他博客也许写的更详细。

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

吐槽:记得第一次做这题是大一到大二的暑假,12年8月多,以前就没A,那时wa了26发放弃了,最近几天又旧题重拾,结果依然纠结,所有情况都考虑了(12年就考虑全了),还是WA,蛋疼死我了,各种数据各种过,就是wa,最终在今天试eps试出了AC!!至此总共wa了51次。。。。。。。。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define eps 1e-6
using namespace std;
bool linecross(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4,double &x5,double &y5)
{
    if(((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)>0&&(x2-x1)*(y4-y1)-(y2-y1)*(x4-x1)>0)||((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)<0&&(x2-x1)*(y4-y1)-(y2-y1)*(x4-x1)<0))return false;
    if(((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3)>0&&(x4-x3)*(y2-y3)-(y4-y3)*(x2-x3)>0)||((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3)<0&&(x4-x3)*(y2-y3)-(y4-y3)*(x2-x3)<0))return false;
    if((y2-y1)*(x4-x3)==(y4-y3)*(x2-x1))return false;
    if(x1==x2)
    {
        x5=x1;
        y5=((y3-y4)*x1+x3*y4-x4*y3)/(x3-x4);
    }
    else if(x3==x4)
    {
        x5=x3;
        y5=((y1-y2)*x3+x1*y2-x2*y1)/(x1-x2);
    }
    else
    {
        x5=((x1*y2-x2*y1)*(x3-x4)-(x3*y4-x4*y3)*(x1-x2))/((y3-y4)*(x1-x2)-(y1-y2)*(x3-x4));
        y5=((y3-y4)*x5+x3*y4-x4*y3)/(x3-x4);
    }
    return true;
}
int main()
{
    //freopen("2826.txt", "w", stdout);
    double x1,x2,x3,x4,x5,y1,y2,y3,y4,y5;
    double a1,b1,a2,b2;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
        if(linecross(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5))
        {
            if(y1==y2||y3==y4)
            {
                cout<<"0.00"<<endl;
                continue;
            }
            if(y1>y2)
            {
                a1=x1;
                b1=y1;
            }
            else
            {
                a1=x2;
                b1=y2;
            }
            if(y3>y4)
            {
                a2=x3;
                b2=y3;
            }
            else
            {
                a2=x4;
                b2=y4;
            }
            if(y5>=b1||y5>=b2)
            {
                cout<<"0.00"<<endl;
                continue;
            }
            if(b1==b2)
            {
                printf("%.2f\n",fabs(fabs(a1-a2)*fabs(b1-y5)/2+eps));
                continue;
            }
            if(a1>x5&&a2>x5&&a1>=a2&&(b1-y5)*(a2-x5)>=(b2-y5)*(a1-x5))
            {
                cout<<"0.00"<<endl;
                continue;
            }
            else if(a1>x5&&a2>x5&&a1<=a2&&(b1-y5)*(a2-x5)<=(b2-y5)*(a1-x5))
            {
                cout<<"0.00"<<endl;
                continue;
            }
            else if(a1<x5&&a2<x5&&a1>=a2&&(b1-y5)*(a2-x5)>=(b2-y5)*(a1-x5))
            {
                cout<<"0.00"<<endl;
                continue;
            }
            else if(a1<x5&&a2<x5&&a1<=a2&&(b1-y5)*(a2-x5)<=(b2-y5)*(a1-x5))
            {
                cout<<"0.00"<<endl;
                continue;
            }
            if(b1>b2)
            {
                swap(a1,a2);
                swap(b1,b2);
            }
            if(x5==a2)
            {
                printf("%.2f\n",fabs(fabs(a1-a2)*fabs(b1-y5)/2+eps));
                continue;
            }
            linecross(x5,y5,a2,b2,x5,b1,a2,b1,x1,y1);
            printf("%.2f\n",fabs(fabs(x1-a1)*fabs(b1-y5)/2+eps));
            continue;

        }
        else cout<<"0.00"<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值