题目
题意:两条直线组成一个图形,能装多少雨水。
思路:如果可以,就会围成一个三角形。两条边的最高点 中 低点的y坐标为围成的三角形的上边的y坐标,再求出交点坐标,求面积。(不看讨论区真做不出来)。
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#define ll long long
#define llu unsigned long long
using namespace std;
const double eps = 1e-8;
struct Point {
double x,y;
Point (double x = 0,double y = 0) : x(x),y(y) {}
};
Point a,b,c,d;
bool dcmp(double x) {
if(fabs(x)-0.0 <= eps) return true;
return false;
}
double cross(Point a,Point b,Point c) {
if(dcmp(((b.x-a.x)*(c.y-a.y)) - ((c.x-a.x)*(b.y-a.y)))) return 0; //卡精度!!!
return ((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y));
}
bool pdC(Point a,Point b,Point c,Point d) { //判断两线是否重合
if((dcmp(a.x-c.x)&&(dcmp(a.y-c.y)) && (dcmp(b.x-d.x))&&dcmp(b.y-d.y))
|| (dcmp(a.x-d.x)&&(dcmp(a.y-d.y)) && (dcmp(b.x-c.x))&&dcmp(b.y-c.y))) return true;
return false;
}
bool pdJ(Point a,Point b,Point c,Point d) { //判断是否相交
if(min(a.x,b.x) <= max(c.x,d.x) && min(c.x,d.x) <= max(a.x,b.x)
&& min(a.y,b.y) <= max(c.y,d.y) && min(c.y,d.y) <= max(a.y,b.y)) {
if(cross(a,b,c)*cross(a,b,d) <= 0 && cross(c,d,a)*cross(c,d,b) <= 0) {
return true;
}
}
return false;
}
bool pdP(Point a,Point b) { // 判断是否和x轴平行
if(dcmp(a.y - b.y)) return true;
return false;
}
bool pdT(Point a,Point b) { //判断线为点
if(dcmp(a.x-b.x) && dcmp(a.y-b.y)) return true;
return false;
}
double Pd(Point a,Point b,Point c,Point d) { //求面积 (判断有一个垂直x轴)
if(dcmp(a.x-b.x) && dcmp(c.x-d.x)) {
return 0;
}
else if(dcmp(a.x-b.x)) { //垂直x轴
double t1 = ((c.y-d.y)/(c.x-d.x));
Point z1,z2;
if(c.y>d.y) z2 = c;
else z2 = d;
if(a.y > b.y) z1 = a;
else z1 = b;
double Maxy = min(z1.y,z2.y);
Point ji;
ji.x = a.x;
ji.y = t1*a.x - t1*c.x + c.y;
double lx = (Maxy - c.y+t1*c.x)/t1;
return (fabs(lx-a.x))*(Maxy-ji.y)/2;
}
else if(dcmp(c.x-d.x)) {
double t1 = ((a.y-b.y)/(a.x-b.x));
Point z1,z2;
if(c.y>d.y) z2 = c;
else z2 = d;
if(a.y > b.y) z1 = a;
else z1 = b;
double Maxy = min(z1.y,z2.y);
Point ji;
ji.x = c.x;
ji.y = t1*c.x - t1*a.x+a.y;
double lx = (Maxy - a.y+t1*a.x)/t1;
return (fabs(lx-c.x))*(Maxy-ji.y)/2;
}
else {
double t1 = ((a.y-b.y)/(a.x-b.x));
double t2 = ((c.y-d.y)/(c.x-d.x));
if(dcmp(t1-t2)) return 0;
Point z1,z2;
if(c.y > d.y) z2 = c;
else z2 = d;
if(a.y > b.y) z1 = a;
else z1 = b;
if(t1*t2 > 0) {
if(t1 > t2) {
if(z1.x-z2.x >= 0) return 0;
}
if(t2 > t1) {
if(z2.x-z1.x >= 0) return 0;
}
}
double Maxy = min(z1.y,z2.y);
Point ji;
double Maxx1 = (Maxy-a.y+t1*a.x)/t1;
double Maxx2 = (Maxy-c.y+t2*c.x)/t2;
ji.x = (t1*a.x-t2*c.x+c.y-a.y)/(t1-t2);
ji.y = t1*ji.x-t1*a.x+a.y;
return (fabs(Maxx2-Maxx1)*(Maxy-ji.y))/2;
}
}
int main(){
int t; scanf("%d",&t);
while(t--) {
scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);
if(pdT(a,b) || pdT(c,d)) { //线为点
printf("0.00\n"); continue;
}
if(pdC(a,b,c,d)) { //重合
printf("0.00\n"); continue;
}
if(!pdJ(a,b,c,d)) { //相交
printf("0.00\n"); continue;
}
if(pdP(a,b) || pdP(c,d)) { // 平行x轴
printf("0.00\n"); continue;
}
double s;
s = Pd(a,b,c,d);
printf("%.2f\n",s);
}
return 0;
}