题意:用两条线段接雨水,雨水是垂直落下的,问我们用给定的两条线段能接到多少水。
分析:看起来很简单,写起来略麻烦,先排除不能接到水的情况:
1. 两条线段不相交;
2. 其中任意一条线段水平;
3. 两条线段重合;
4. 相交的情况下,最高的端点遮住了次高的端点
最后求线段交点确定三角形并用叉积求面积。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps = 1e-8; const double PI = acos(-1.0); const int N = 100010; int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1; } struct Point { double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉积 double operator ^(const Point &b)const { return x*b.y - y*b.x; } }; struct Line { Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; } //两直线相交求交点 //第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交 //只有第一个值为2时,交点才有意义 pair<int,Point> operator &(const Line &b)const { Point res=s; if(sgn((s-e)^(b.s-b.e))==0) { if(sgn((s-b.e)^(b.s-b.e))==0) return make_pair(0,res); else return make_pair(1,res); } double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x+=(e.x-s.x)*t; res.y+=(e.y-s.y)*t; return make_pair(2,res); } }; //判断线段相交 bool inter(Line l1,Line l2) { return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 && sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0; } int main() { int T; Line l1,l2; scanf("%d",&T); while(T--) { double a,b,c,d; scanf("%lf%lf%lf%lf",&a,&b,&c,&d); l1=Line(Point(a,b),Point(c,d)); scanf("%lf%lf%lf%lf",&a,&b,&c,&d); l2=Line(Point(a,b),Point(c,d)); if(sgn(l1.s.y-l1.e.y)==0||sgn(l2.s.y-l2.e.y)==0||!inter(l1,l2)) { puts("0.00"); continue; } if(sgn(l1.s.y-l1.e.y)<0)swap(l1.s,l1.e); if(sgn(l2.s.y-l2.e.y)<0)swap(l2.s,l2.e); if(inter(Line(l1.s,Point(l1.s.x,100000)),l2)||inter(Line(l2.s,Point(l2.s.x,100000)),l1)) { puts("0.00"); continue; } if(sgn(l1.s.y-l2.s.y)<0) { Point p=(l1&l2).second; Point p1=(Line(l1.s,Point(100000,l1.s.y))&l2).second; double ans=fabs((l1.s-p)^(p1-p))/2; printf("%.2lf\n",ans); } else { Point p=(l1&l2).second; Point p1=(Line(l2.s,Point(100000,l2.s.y))&l1).second; double ans=fabs((l2.s-p)^(p1-p))/2; printf("%.2lf\n",ans); } } }
时间: 2024-12-14 18:12:20