題意:給兩個木板,問這兩個木板能接多少水
思路:首先,如果有一個平行於x軸的,或者兩個不相交,或者重合的情況下答案就是0.00。相交的時候分爲兩種情況,一種是斜率不同,這個很好處理,就是較低的點做個平行於x軸的直線,然後圍成的三角形的面積就是答案。如果斜率相同,有如下幾種情況
代碼:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<list>
using namespace std;
const double INF = 1e200;
const double EP = 1e-10;
const int maxn = 4000;
//const double PI = acos(-1);
struct POINT{///點 定義
double x;
double y;
POINT(double a = 0,double b = 0){x = a;y = b;}
};
struct SEGMENT{///line segment///線段 定義
POINT s;
POINT e;
SEGMENT(POINT a,POINT b){s = a;e = b;}
SEGMENT(){}
};
struct LINE{///ax + by + c = 0&&a >= 0///一般式
double a;
double b;
double c;
LINE(double da,double db,double dc){a = da;b = db;c = dc;}
LINE(double x1,double y1,double x2,double y2){///根據兩個點求出一般式
a = y1 - y2;b = x2 - x1;c = x1*y2 - x2*y1;
if(a < 0){a*=-1;b*=-1;c*=-1;}
}
};
double multiply(POINT sp,POINT ep,POINT op){///向量op->sp X op->ep的叉乘,小於0:ep在op->sp順時針方向//大於0:0:ep在op->sp逆時針方向//等於0:三點共線
return ((sp.x - op.x)*(ep.y - op.y) - (ep.x - op.x)*(sp.y - op.y));
}
double dotmultiply(POINT p1,POINT p2,POINT p0){
return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y));
}
bool online(SEGMENT l,POINT p){///判斷點是否在線段上
return ((multiply(l.e,p,l.s) == 0)&&(((p.x-l.s.x)*(p.x-l.e.x))<= 0)&&(((p.y-l.s.y)*(p.y-l.e.y)) <= 0));
}
bool intersect(SEGMENT u,SEGMENT v){///兩線段相交(包括端點),返回true
return ((max(u.s.x,u.e.x) >= min(v.s.x,v.e.x))&&
(max(v.s.x,v.e.x) >= min(u.s.x,u.e.x))&&
(max(u.s.y,u.e.y) >= min(v.s.y,v.e.y))&&
(max(v.s.y,v.e.y) >= min(u.s.y,u.e.y))&&
(multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s) >= -EP)&&
(multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s) >= -EP));
}
bool intersect_a(SEGMENT u,SEGMENT v){///兩線段相交(不包括端點)
return ((intersect(u,v))&&
!online(u,v.s)&&
!online(u,v.e)&&
!online(v,u.e)&&
!online(v,u.s));
}
int lineintersect(LINE l1,LINE l2,POINT &p){///求兩直線交點,有交點返回1和交點,沒有返回0,重合返回2
double d = l1.a*l2.b-l2.a*l1.b;
double d2 = l1.a*l2.c-l2.a*l1.c;
double d3 = l1.b*l2.c-l2.b*l1.c;
if(fabs(d) < EP&&fabs(d2) < EP&&fabs(d3) < EP)return 2;
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
if(fabs(d) < EP)return 0;
return 1;
}
double point_dis(POINT a,POINT b){///求兩點距離
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
///************************************************************************************************************************************
double dis(POINT a,POINT b){
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x+y*y);
}
int main(){
//freopen("in.txt","r",stdin);
int T;
cin>>T;
SEGMENT sa,sb;
while(T --){
double x1,y1,x2,y2;
POINT a,b;
cin>>x1>>y1>>x2>>y2;
if(y1 > y2){swap(x1,x2);swap(y1,y2);}
a.x = x1,a.y = y1;
b.x = x2,b.y = y2;
sa.s = a,sa.e = b;
cin>>x1>>y1>>x2>>y2;
if(y1 > y2){swap(x1,x2);swap(y1,y2);}
a.x = x1,a.y = y1;
b.x = x2,b.y = y2;
sb.s = a,sb.e = b;
if(fabs(sa.s.y-sa.e.y) < EP||fabs(sb.s.y - sb.e.y) < EP)puts("0.00");
else{
bool flag = intersect(sa,sb);
if(!flag)puts("0.00");
else{
LINE la(sa.s.x,sa.s.y,sa.e.x,sa.e.y),lb(sb.s.x,sb.s.y,sb.e.x,sb.e.y);
POINT jiao_dian;
int linn = lineintersect(la,lb,jiao_dian);
if(linn == 2){puts("0.00");continue;}
if(la.b*la.a*lb.a*lb.b > 0){///xie lv xiang tong
bool ok = 0;
if(sa.e.y < sb.e.y){swap(sa,sb);swap(la,lb);}
//cout<<la.b*la.a<<endl;
if(((la.b/(la.a+EP) - lb.b/(lb.a+EP))*(sa.e.x-sb.e.x)) < 0)ok = 1;
if(ok == 1){
LINE tmp(sb.e.x,sb.e.y,sb.e.x+10,sb.e.y);
POINT point_tmp;
lineintersect(tmp,la,point_tmp);
double ans = (fabs(point_tmp.x - sb.e.x))*(fabs(jiao_dian.y - sb.e.y));
printf("%.2f\n",ans/2.0+EP);//puts("aaaaaaaa");
}
else puts("0.00");
}
else{
if(sa.e.y < sb.e.y){swap(sa,sb);swap(la,lb);}
LINE tmp(sb.e.x,sb.e.y,sb.e.x+10,sb.e.y);
POINT point_tmp;
lineintersect(tmp,la,point_tmp);
double ans = (fabs(point_tmp.x - sb.e.x))*(fabs(jiao_dian.y - sb.e.y));
printf("%.2f\n",ans/2.0+EP);
}
}
}
}
return 0;
}