写了一句if(area<0) area=-area;并没毛用,WA一万年,照着discuss里面的说法试了一下printf(area+eps)就过了。。。
行行,以后计算几何题一律+eps输出,卧佛了
这题讨论还是很多了。
首先,我们要找出不会积水的情况
1.没有交点
2.两线段平行或重合
3.有一条线段垂直于地面和天
4.一根线段遮挡住了第二根线段,也就是遮挡住了朝天的开口。
然后,就可以求出朝天的开口的面积了,以较低的那个点作水平线交于另外一条线段,然后用叉积求面积
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 1e-8
using namespace std;
inline int sgn(double x)
{
if(x<eps && x>-eps) return 0;
if(x>0) return 1;
else return -1;
}
struct point
{
double x,y;
point(double a=0,double b=0)
{
x=a;y=b;
}
point operator + (const point &b)const
{
return point(x+b.x,y+b.y);
}
point operator - (const point &b)const
{
return point(x-b.x,y-b.y);
}
friend point operator * (double t,const point b)
{
return point(t*b.x,t*b.y);
}
}p[10];
inline double dot(const point a,const point b)
{
return a.x*b.x+a.y*b.y;
}
inline double det(const point a,const point b)
{
return a.x*b.y-a.y*b.x;
}
struct line
{
point s,e;
double k;
line(point a=point(),point b=point())
{
s=a;e=b;
}
}a[5],L;
double area;
bool ans;
inline void prework()
{
for(int i=1;i<=4;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
}
inline bool point_on_seg(point &p,line &a)
{
return sgn(det(p-a.s,p-a.e))==0 && sgn(dot(p-a.s,p-a.e))<=0;
}
inline bool parallel(line &l1,line &l2)
{
return !sgn(det(l1.e-l1.s,l2.e-l2.s));
}
inline bool cross(line l1,line l2)
{
line vec=line(l1.s,l1.e-l1.s);
if(parallel(l1,l2))//覆盖的情况这里不行
return false;
if(det((l2.s-vec.s),vec.e)*det(vec.e,(l2.e-vec.s))<0-eps)
return false;
if(det((l2.s-l1.s),(l2.e-l1.s))*det((l2.s-l1.e),(l2.e-l1.e))>0+eps)
return false;
return true;
}
inline void seg_intersec(line l1,line l2,point &insec)
{
point v=point(l1.e-l1.s),w=point(l2.e-l2.s);
double t=det(l2.s-l1.s,w)/det(v,w);
insec=l1.s+t*v;
}
inline void mainwork()
{
if(p[1].y>p[2].y) swap(p[1],p[2]);
if(p[3].y>p[4].y) swap(p[3],p[4]);
ans=true;
if(!cross(line(p[1],p[2]),line(p[3],p[4])))
ans=false;
if(sgn(p[1].y-p[2].y)==0 || sgn(p[3].y-p[4].y)==0)
ans=false;
double mxx,mxy;
double k1=atan2(p[2].y-p[1].y,p[2].x-p[1].x);
double k2=atan2(p[4].y-p[3].y,p[4].x-p[3].x);
if(p[2].x<p[1].x && p[4].x<p[3].x)
{
if(p[2].x<p[4].x+eps && p[2].y>p[4].y && k1<k2)
ans=false;
if(p[4].x<p[2].x+eps && p[4].y>p[2].y && k2<k1)
ans=false;
}
if(p[2].x>p[1].x && p[4].x>p[3].x)
{
if(p[2].x>p[4].x-eps && p[2].y>p[4].y && k1>k2)
ans=false;
if(p[4].x>p[2].x-eps && p[4].y>p[2].y && k2>k1)
ans=false;
}
if(!ans)
return;
point insec,d2;
double t;
seg_intersec(line(p[1],p[2]),line(p[3],p[4]),insec);
if(p[2].y<p[4].y)
{
t=(p[2].y-p[3].y)/(p[4].y-p[3].y);
d2=p[3]+(t*(p[4]-p[3]));
area=det(point(p[2]-insec),point(d2-insec))/2;
}
else
{
t=(p[4].y-p[1].y)/(p[2].y-p[1].y);
d2=p[1]+(t*(p[2]-p[1]));
area=det(point(d2-insec),point(p[4]-insec))/2;
}
if(area<0.0)
area=-area;
}
inline void print()
{
if(ans)
printf("%.2f\n",area+eps);
else
puts("0.00");
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}