雨水竖直下落,给定两条线段,问最多能接多少雨水?
毒瘤计算几何题目(qwq)
先考虑一下接不到雨水的情况:
1.线段不相交
2.有一条线段水平
3.平行
4.小于(90^{。})的夹角不朝上
怎么判断这些情况?
第一种:跨立实验
第二种:直接看纵坐标
第三种:求斜率
第四种:过最高点较低的线段的最高点做一条垂直(x)轴的直线,如果与另一条线段相交则接不到雨水
判断完了之后算一个三角形面积就好了
注意有可能存在竖直的线段,需要特判
说起来一套一套的,写来一愣一愣的(qwq)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
namespace red{
#define y1 qwq
#define int long long
#define eps (1e-10)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
int haku;
struct node
{
double x,y;
node (double tx=0,double ty=0){x=tx,y=ty;}
inline double operator ^ (const node &t) const//叉积
{
return x*t.y-y*t.x;
}
inline node operator - (const node &t) const
{
return node(x-t.x,y-t.y);
}
};
struct seg
{
node a,b;
double k;
inline double slope() const//斜率
{
return (a.y-b.y)/(a.x-b.x);
}
inline double turn(node t1,node t2,node t3) const//t1->t2和t1->t3的叉积
{
return (t2-t1)^(t3-t1);
}
inline bool across(const seg &t) const//跨立实验
{
double x=turn(a,b,t.a)*turn(a,b,t.b);
if(x>=eps) return 0;
x=turn(t.a,t.b,a)*turn(t.a,t.b,b);
if(x>=eps) return 0;
return 1;
}
inline node get_node(const seg &t) const//求交点
{
double b1=a.y-a.x*k,b2=t.a.y-t.a.x*t.k;
double x=(b2-b1)/(k-t.k);
double y=k*x+b1;
return node(x,y);
}
inline node y_node(double y) const//给y值求点
{
double bb=a.y-a.x*k;
double x=(y-bb)/k;
return node(x,y);
}
inline node x_node(double x) const//给x值求点
{
double bb=a.y-a.x*k;
double y=k*x+bb;
return node(x,y);
}
}d1,d2,d3;
inline double are(node a,node b,node c)//三角形面积
{
return (a.x*b.y+b.x*c.y+c.x*a.y-a.x*c.y-b.x*a.y-c.x*b.y)/2;
}
inline void solve()
{
if(d1.a.x!=d1.b.x) swap(d1,d2);
if((d1.a.x==d1.b.x&&d2.a.x==d2.b.x)||!d1.across(d2)||d2.b.x==d1.a.x||(d2.a.y==d2.b.y))
{
puts("0.00");
return;
}
node p=d2.x_node(d1.a.x);
double t=min(fabs(d1.b.y-p.y),fabs(d2.b.y-p.y));
double h=fabs(d2.y_node(min(d1.b.y,d2.b.y)).x-d1.a.x);
printf("%.2lf
",h*t/2+eps);
}
inline void main()
{
haku=read();
while(haku--)
{
d1.a.x=read(),d1.a.y=read(),d1.b.x=read(),d1.b.y=read();d1.k=d1.slope();
if(d1.a.y>d1.b.y) swap(d1.a,d1.b);
d2.a.x=read(),d2.a.y=read(),d2.b.x=read(),d2.b.y=read();d2.k=d2.slope();
if(d2.a.y>d2.b.y) swap(d2.a,d2.b);
if(d1.b.y<d2.b.y) swap(d1,d2);
if(d1.a.x==d1.b.x||d2.a.x==d2.b.x)//竖直的线段特判
{
solve();
continue;
}
if(fabs(d1.k-d2.k)<eps||fabs(d1.k)<eps||fabs(d2.k)<eps||!d1.across(d2))
{
puts("0.00");
continue;
}
d3.a=d2.b,d3.b=node(d2.b.x,10002);//竖直的直线
if(d1.across(d3))
{
puts("0.00");
continue;
}
node p=d1.get_node(d2),r=d2.b,q=d1.y_node(r.y);
printf("%.2lf
",fabs(are(p,r,q))+eps);
}
}
}
signed main()
{
red::main();
return 0;
}
/*
1
9235 7382 3788 328 4607 2583 7068 3480
*/