题目:
题意:
给出两条线段,雨水从空中竖直落下,问线段上能积多少水。
题解:
一道特判超~~~多的题目,下见注释咯
这道题精度会有-0.00?!加个fabs吧。
这题的题解。。。真是敷衍啊
那就加个对于距离的讲解吧,虽然这个题没有用
点到直线的距离(用面积法啦)【如果a旋转到b是逆时针,则叉积为正,否则叉积为负】
double DisDL(Point P,Point A,Point B)
{
Vector v=B-A,w=P-A;
return fabs(Cross(v,w)/Len(v));
}
点到线段的距离?如果做垂直能在直线上,那就是点到直线的距离,否则就是到某个端点的距离
用点积做比较简单【如果a b夹角大于90度,点积为负,小于90度,点积为正】
double DisTS(Point P,Point A,Point B)
{
if (A==B) return Len(P-A);
Vector v=B-A,w=P-A,u=P-B;
if (dcmp(Dot(v,w))<0) return Len(w);
else if (dcmp(Dot(v,u))>0) return Len(u);
else return fabs(Cross(v,w)/Len(v));
}
上面就是关于距离的基本知识
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-9;
int dcmp(double x)
{
if (x<=eps && x>=-eps) return 0;
return (x>0)?1:-1;
}
struct po
{
double x,y;
po(double X=0,double Y=0){x=X;y=Y;}
};
po operator +(po x,po y){return po(x.x+y.x,x.y+y.y);}
po operator -(po x,po y){return po(x.x-y.x,x.y-y.y);}
po operator *(po x,double y){return po(x.x*y,x.y*y);}
double dj(po x,po y){return x.x*y.x+x.y*y.y;}
double cj(po x,po y){return x.x*y.y-x.y*y.x;}
double len(po x){return sqrt(dj(x,x));}
bool jd(po a,po b,po c,po d)//有交点且不重合
{
double d1=dcmp(cj(c-a,b-a)),d2=dcmp(cj(d-a,b-a));
double d3=dcmp(cj(a-d,c-d)),d4=dcmp(cj(b-d,c-d));
return d1!=d2 && d3!=d4;
}
po dd(po a,po b,po c,po d)//交点坐标
{
po A=a-c,B=b-a,D=d-c;
double t=cj(D,A)/cj(B,D);
return a+B*t;
}
int main()
{
int T;scanf("%d",&T);
while (T--)
{
double x1,y1,x2,y2,x3,y3,x4,y4,dis=0;
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
po a=po(x1,y1),b=po(x2,y2),c=po(x3,y3),d=po(x4,y4);
if (!jd(a,b,c,d)) {printf("0.00\n");continue;}//没有交点|重合
if (y1==y2 || y3==y4){printf("0.00\n");continue;} //平的肯定接不住水啊
if (y1>y2) swap(a,b);
if (y3>y4) swap(c,d);//b,d头在上
po now=dd(a,b,c,d);
double h=min(b.y-now.y,d.y-now.y);
if (dcmp(h)<=0) {printf("0.00\n");continue;}
if (b.y<d.y) swap(b,d),swap(a,c);//a,b线段在上
if (a.x!=b.x)
{
double k1=(b.y-a.y)/(b.x-a.x);
double k2=(d.y-c.y)/(d.x-c.x);
if (k1*k2>0 && ((dcmp(k1)<0 && b.x<=d.x && dcmp(k1-k2)<0) || (dcmp(k1)>0 && b.x>=d.x && dcmp(k1-k2)>0))) {printf("0.00\n");continue;}
//斜率一正一负肯定接的到水,两正|负就要看看上面那个能不能完全挡住下面那个
double b1=a.y-k1*a.x;
double xd=(d.y-b1)/k1;
dis=fabs(d.x-xd);
}else dis=fabs(d.x-b.x);
printf("%.2lf\n",fabs(dis*h/2));
}
}