链接 An Easy Problem?!
题意
两个木板,问能接多少雨水;
思路
考虑多种情况:
- 不相交
- 一个木板与x轴平行
- 长木板挡住接水
第三种情况大概是这样的
情况都考虑周全即可;
AC代码
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
const double eps = 1e-8;
const int N = 10010;
int sign(double x)
{
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
return 1;
}
struct Point
{
double x, y;
Point(){}
Point(double _x, double _y)
{
x = _x, y = _y;
}
Point operator -(const Point &a) const
{
return Point(x - a.x, y - a.y);
}
//叉积
double operator ^(const Point &a) const
{
return x * a.y - y * a.x;
}
//点积
double operator *(const Point &a) const
{
return x * a.x + y * a.y;
}
};
struct Line
{
Point st, ed;
Line(){}
Line(Point _st, Point _ed)
{
st = _st, ed = _ed;
}
//两直线相交求交点
//只有第一个值为2时,交点才有意义;
pair<int, Point> operator &(const Line &a) const
{
Point res = st;
if (sign((st - ed) ^ (a.st - a.ed)) == 0)
{
//重合
if (sign((st - a.ed) ^ (a.st - a.ed)) == 0) return make_pair(0, res);
//平行
return make_pair(1, res);
}
double t = ((st - a.st) ^ (a.st - a.ed)) / ((st - ed) ^ (a.st - a.ed));
res.x += (ed.x - st.x) * t;
res.y += (ed.y - st.y) * t;
//求交点
return make_pair(2, res);
}
};
bool intersect(Line a, Line b)
{
return
max(a.st.x, a.ed.x) >= min(b.st.x, b.ed.x) &&
max(b.st.x, b.ed.x) >= min(a.st.x, a.ed.x) &&
max(a.st.y, a.ed.y) >= min(b.st.y, b.ed.y) &&
max(b.st.y, b.ed.y) >= min(a.st.y, a.ed.y) &&
sign((b.st - a.ed) ^ (a.st - a.ed)) * sign((b.ed - a.ed) ^ (a.st - a.ed)) <= 0 &&
sign((a.st - b.ed) ^ (b.st - b.ed)) * sign((a.ed - b.ed) ^ (b.st - b.ed)) <= 0;
}
bool judge(Line a, Line b)
{
//平行于x轴
if (sign(a.st.y - a.ed.y) == 0 || sign(b.st.y - b.ed.y) == 0) return true;
//不相交
if (!intersect(a, b)) return true;
//口被封上
if (intersect(Line(a.st, Point(a.st.x, 10000000)), b) || intersect(Line(b.st, Point(b.st.x, 10000000)), a)) return true;
}
void solve(Line a, Line b)
{
pair<int, Point> pr;
pr = a & b;
Point p = pr.second;
double ans1;
pr = b & Line(Point(10000000, a.st.y), a.st);
Point p1 = pr.second;
ans1 = fabs((a.st - p) ^ (p1 - p)) / 2;
double ans2;
pr = a & Line(Point(10000000, b.st.y), b.st);
Point pw = pr.second;
ans2 = fabs((b.st - p) ^ (pw - p)) / 2;
printf("%.2lf\n", min(ans1, ans2) + eps);
}
int main()
{
int T;
cin >> T;
while (T --)
{
int x1, y_1, x2, y2, x3, y3, x4, y4;
cin >> x1 >> y_1 >> x2 >> y2 >> x3 >> y3 >> x4 >> y4;
Line l1, l2;
l1 = Line(Point(x1 ,y_1), Point(x2, y2));
l2 = Line(Point(x3, y3), Point(x4, y4));
if (sign(l1.st.y - l1.ed.y) < 0) swap(l1.st, l1.ed);
if (sign(l2.st.y - l2.ed.y) < 0) swap(l2.st, l2.ed);
if (judge(l1, l2)) printf("0.00\n");
else solve(l1, l2);
}
}