不得不说这道题有点爽的样子。。。要考虑很多种细节,可以练练手感,然后的然后我写的好像有点长了。。。
这种题首先思路要理清楚,分为能接到水和不能接到水两种情况,然后能接到水直接用叉乘计算面积
不能接到水的情况有几种要分别讨论
1.有一条线段和x轴平行
2.两条线段不相交
3.两条线段的交点上方不能接到水,也就是说交点与其中一条线段的y坐标最大值那个点重合了
4.两条线段相交,但是位于上方的直线遮盖住了下方的直线
比如这组数据
0 0 2 2
0 0 2 0
只要这些情况都考虑到的话AC还是没问题的,不过我看讨论版里有些人说精度卡的高。。。不理解是哪里卡精度了。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-8;
struct P
{
double x,y;
P(){}
P(double x,double y):x(x),y(y){
}
P operator +(P p){
return P(x+p.x,y+p.y);
}
P operator -(P p){
return P(x-p.x,y-p.y);
}
P operator *(double d){
return P(x*d,y*d);
}
double det(P p){
return x*p.y-y*p.x;
}
};
struct Line
{
P a,b;
};
Line q[2];
int n,t;
P in(P p1,P p2,P q1,P q2){
return p1+(p2-p1)*( (q2-q1).det(q1-p1)/(q2-q1).det(p2-p1) );
}
bool kspc(Line a,Line b)//快速排斥实验
{
if(min(a.a.x,a.b.x)>max(b.a.x,b.b.x) || max(a.a.x,a.b.x)<min(b.a.x,b.b.x))
return 0;
if(min(a.a.y,a.b.y)>max(b.a.y,b.b.y) || max(a.a.y,a.b.y)<min(b.a.y,b.b.y))
return 0;
return 1;
}
P r;
bool judge() //判断是否能接水
{
//判断不相交或者共线返回1
if(!kspc(q[0],q[1]))
return 1;
if(!((q[0].a-q[1].a).det(q[1].b-q[1].a)*(q[0].b-q[1].a).det(q[1].b-q[1].a)<=0 && (q[1].a-q[0].a).det(q[0].b-q[0].a)*(q[1].b-q[0].a).det(q[0].b-q[0].a)<=0))
return 1;
if((q[0].a-q[1].a).det(q[1].a-q[1].b)==0.0 && (q[0].b-q[1].a).det(q[1].a-q[1].b)==0.0)
return 1;
//判断是否有水平线,返回1
if(q[0].a.y==q[0].b.y || q[1].a.y==q[1].b.y)
return 1;
//判断交点是否在最高点
if((q[0].a-q[1].a).det(q[1].a-q[1].b)==0.0 || (q[1].a-q[0].a).det(q[0].a-q[0].b)==0.0)
return 1;
//最高点在交点同侧且覆盖
r=in(q[0].a,q[0].b,q[1].a,q[1].b);
if(q[0].a.x<=r.x && q[1].a.x<=r.x)
{
if(q[0].a.y>q[1].a.y && q[0].a.x<=q[1].a.x)
{
if((q[0].a-r).det(q[1].a-r)>=0)
return 1;
}
else if(q[0].a.y<=q[1].a.y && q[0].a.x>=q[1].a.x)
{
if((q[1].a-r).det(q[0].a-r)>=0)
return 1;
}
}
if(q[0].a.x>=r.x && q[1].a.x>=r.x)
{
if(q[0].a.y>q[1].a.y && q[0].a.x>=q[1].a.x)
{
if((q[0].a-r).det(q[1].a-r)<=0)
return 1;
}
else if(q[0].a.y<=q[1].a.y && q[0].a.x<=q[1].a.x)
{
if((q[1].a-r).det(q[0].a-r)<=0)
return 1;
}
}
return 0;
}
double ans;
void solve() //计算面积
{
P l,d;
double asd;
if(q[0].a.y==q[1].a.y)
{
asd=(q[0].a-r).det(q[1].a-r);
}
else if(q[0].a.y<q[1].a.y)
{
if(q[0].a.x<r.x && q[1].a.x<r.x)
{
l.x=10000000.0;
l.y=q[0].a.y;
d=in(q[0].a,l,q[1].a,q[1].b);
asd=(d-r).det(q[0].a-r);
}
else
{
l.x=-10000000.0;
l.y=q[0].a.y;
d=in(q[0].a,l,q[1].a,q[1].b);
asd=(d-r).det(q[0].a-r);
}
}
else
{
if(q[0].a.x<r.x && q[1].a.x<r.x)
{
l.x=10000000.0;
l.y=q[1].a.y;
d=in(q[1].a,l,q[0].a,q[0].b);
asd=(d-r).det(q[1].a-r);
}
else
{
l.x=-10000000.0;
l.y=q[1].a.y;
d=in(q[1].a,l,q[0].a,q[0].b);
asd=(d-r).det(q[1].a-r);
}
}
if(asd<0)
asd=-asd;
ans=asd/2.0;
printf("%.2lf\n",ans);
}
int main()
{
// freopen("intput.txt","r",stdin);
// freopen("output.txt","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%lf%lf",&q[0].a.x,&q[0].a.y,&q[0].b.x,&q[0].b.y);
scanf("%lf%lf%lf%lf",&q[1].a.x,&q[1].a.y,&q[1].b.x,&q[1].b.y);
if(q[0].a.y<q[0].b.y)
swap(q[0].a,q[0].b);
if(q[1].a.y<q[1].b.y)
swap(q[1].a,q[1].b);
if(judge())
printf("0.00\n");
else
solve();
}
return 0;
}