求线段交点

德布是一个很大的可乐饮酒者,但他无法帮助它。

为了少喝可乐,他设计了以下装置:

一种长度和高度几乎无限的水箱,底部有无限量的可乐。

在水箱中间有两个木板,木板位于距离水箱边缘无限远的地方,木板和可乐之间的距离是无限的,两个木板可能相交,

Debu将在中午将罐子倒置(稍后完成),可乐将垂直下降。可乐的速度很快,可乐到达底部片刻,所以一些

木板可以保留可乐(因为两块木板可能相交),而德布会喝木板保留的可乐

晚上,Debu将重复这个过程并再次享用可乐。

现在让我们计算一天可以喝多少可乐德布(木板和水箱的宽度为1)
在这里插入图片描述
输入
第一行是整数T,表示测试用例的数量(1 <= T <= 1e5)。

每个测试用例有8个整数:x1,y1,x2,y2,x3,y3,x4,y4。

(x1,y1),(x2,y2)是一个挡板的端点,(x3,y3),(x4,y4)是端点的端点。

其他挡板,每个整数不超过10,000。

产量
对于每个测试用例输出一行包含一个实数,精度最多为两位小数 - 可乐的数量。

例子
输入:
1
1 1 2 2 1 1 0 2
输出:
1.00

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define ll long long
using namespace std;
struct node
{
    double x,y;
};
int get_line_intersection(double  p0_x, double  p0_y, double  p1_x, double  p1_y,
                          double  p2_x, double  p2_y, double  p3_x, double  p3_y, double  *i_x, double  *i_y)
{
    double  s02_x, s02_y, s10_x, s10_y, s32_x, s32_y, s_numer, t_numer, denom, t;
    s10_x = p1_x - p0_x;
    s10_y = p1_y - p0_y;
    s32_x = p3_x - p2_x;
    s32_y = p3_y - p2_y;

    denom = s10_x * s32_y - s32_x * s10_y;
    if (denom == 0)
        return 0;
    bool denomPositive = denom > 0;

    s02_x = p0_x - p2_x;
    s02_y = p0_y - p2_y;
    s_numer = s10_x * s02_y - s10_y * s02_x;
    if ((s_numer < 0) == denomPositive)
        return 0;

    t_numer = s32_x * s02_y - s32_y * s02_x;
    if ((t_numer < 0) == denomPositive)
        return 0;

    if (fabs(s_numer) > fabs(denom) || fabs(t_numer) > fabs(denom))
        return 0;
    t = t_numer / denom;
    if (i_x != NULL)
        *i_x = p0_x + (t * s10_x);
    if (i_y != NULL)
        *i_y = p0_y + (t * s10_y);

    return 1;
}
double cross(node a,node b,node c)
{
    a.x=a.x-c.x;
    a.y=a.y-c.y;
    b.x=b.x-c.x;
    b.y=b.y-c.y;
    return fabs((a.x*b.y-a.y*b.x));
}
node a1,a2,b1,b2;
node r;
int ans;
double res;
void solve1()
{
    if((a2.y==b2.y&&b2.y==r.y)||a1.y==a2.y||b1.y==b2.y)
    {
        return ;
    }
    if(a2.y>b2.y)
    {
        swap(a1,b1);
        swap(a2,b2);
    }
    node k;
    if(b2.x==b1.x)
    {
        k.y=a2.y;
        k.x=b1.x;
        res+=cross(a2,k,r)/2.0;
    }
    else
    {
        double ks=(b2.y-b1.y)/(b2.x-b1.x);
        ks=(a2.y-b1.y)/ks+b1.x;
        k.y=a2.y;
        k.x=ks;
        res+=cross(a2,k,r)/2.0;
    }
}
void solve2()
{
    if(ans==0)
    {
        return ;
    }
    if((a1.y==b1.y&&b1.y==r.y)||a1.y==a2.y||b1.y==b2.y)
    {
        return ;
    }
    if(a1.y<b1.y)
    {
        swap(a1,b1);
        swap(a2,b2);
    }
    node k;
    if(b2.x==b1.x)
    {
        k.y=a1.y;
        k.x=b1.x;
        res+=cross(a1,k,r)/2.0;
    }
    else
    {
        double ks=(b2.y-b1.y)/(b2.x-b1.x);
        ks=b2.x-(b2.y-a1.y)/ks;
        k.y=a1.y;
        k.x=ks;
        res+=cross(a1,k,r)/2.0;
    }
}
int Equal(node a,node b)
{
    if(a.x==b.x&&a.y==b.y)
        return 1;
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        res=0.0;
        scanf("%lf%lf%lf%lf",&a1.x,&a1.y,&a2.x,&a2.y);
        if(a2.y<a1.y)
            swap(a1,a2);
        scanf("%lf%lf%lf%lf",&b1.x,&b1.y,&b2.x,&b2.y);
        if(b2.y<b1.y)
            swap(b1,b2);
        if(Equal(a1,b1))
        {
            r=a1;
        }
        else if( Equal(a2,b2))
        {
            r=a2;
        }//判断是否端点相交***因为这个wa了一发
        else
        {
            ans=get_line_intersection(a1.x,a1.y,a2.x,a2.y,b1.x,b1.y,b2.x,b2.y,&r.x,&r.y);
            if(ans==0)
            {
                printf("0.00\n");
                return 0;
            }
        }
        solve1();
        solve2();
        printf("%.2lf\n",res);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值