HDU4637 Rain on your Fat brother

来源:互联网 发布:软件二次开发端口 编辑:程序博客网 时间:2024/06/10 00:23

任意门: http://acm.hdu.edu.cn/showproblem.php?pid=4637


假设所有雨点都不动,那么可以看做人物向着左上角匀速移动。

求出人物运动的轨迹(一条线段)与所有雨滴的交线段,然后求线段并就可以了。


题目其实很简单,但是很烦啊,记录一下代码。


#pragma comment(linker,"/STACK:102400000,102400000")#include <cstdio>#include <iostream>#include <cstring>#include <cmath>#include <ctime>#include <vector>#include <set>#include <queue>#include <stack>#include <map>#include <algorithm>using namespace std;typedef long long ll;const double eps = 1e-8;const double PI = acos(-1.0);struct Point{double x, y;Point(double x=0, double y=0): x(x), y(y) {}};typedef Point Vector;void print(Point p) {cout << p.x << " " << p.y << endl;}bool operator < (const Point &a, const Point &b) {return a.x > b.x || (a.x == b.x && a.y < b.y);}int dcmp(double x) {if (fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;}bool operator == (const Point &a, const Point &b) {return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}bool operator != (const Point &a, const Point &b) {return !(a == b);}Vector operator + (Vector A, Vector B) {return Vector(A.x+B.x, A.y+B.y);}Vector operator - (Vector A, Vector B) {return Vector(A.x-B.x, A.y-B.y);}Vector operator * (Vector A, double p) {return Vector(A.x*p, A.y*p);}Vector operator / (Vector A, double p) {return Vector(A.x/p, A.y/p);}double Dot(Vector A, Vector B) {return A.x*B.x + A.y*B.y;}double Cross(Vector A, Vector B) {return A.x*B.y - A.y*B.x;}double Length(Vector A) {return sqrt(Dot(A, A));}double Distance(Point A, Point B) {return sqrt(Dot(A-B, A-B));}double Area2(Point A, Point B, Point C) {return abs(Cross(B-A, C-A));}bool OnSegment(Point P, Point A, Point B){return dcmp(Cross(A-P, B-P))==0 && dcmp(Dot(A-P, B-P))<0;}bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1), c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;}Point GetLineIntersection(Point a1, Point a2, Point b1, Point b2){Vector v = a2-a1, w = b2-b1, u = a1-b1;double t = Cross(w, u) / Cross(v, w);return a1 + v*t;}struct Circle{    Point c;    double r;    Circle() {c = Point(0, 0); r = 0;}    Circle(Point c, double r) : c(c), r(r) {}    Point point(double a) {return Point(c.x + r*cos(a), c.y + r*sin(a));}};int GetLineCircleIntersection(Point A, Point B, Circle C, Point &X, Point &Y){    double a = (B-A).x, b = A.x-C.c.x, c = (B-A).y, d = A.y-C.c.y;    double e = a*a+c*c, f = 2*(a*b+c*d), g = b*b+d*d-C.r*C.r;    double delta = f*f - 4*e*g;    if (dcmp(delta) < 0) return 0;    else if (dcmp(delta) == 0)    {        double tt = -f / (2*e);        X = A + (B-A)*tt;        if (dcmp(X.y - C.c.y) > 0 || dcmp(X.y - A.y) < 0 || dcmp(X.y - B.y) > 0) return 0;        return 1;    }    else    {        int ret = 0;        double t1 = (-f - sqrt(delta)) / (2*e);        X = A + (B-A)*t1;        if (dcmp(X.y - C.c.y) > 0 || dcmp(X.y - A.y) < 0 || dcmp(X.y - B.y) > 0)        {            t1 = (-f + sqrt(delta)) / (2*e);            X = A + (B-A)*t1;            if (dcmp(X.y - C.c.y) > 0 || dcmp(X.y - A.y) < 0 || dcmp(X.y - B.y) > 0) return 0;            return 1;        }        ret++;        double t2 = (-f + sqrt(delta)) / (2*e);        Y = A + (B-A)*t2;        if (dcmp(Y.y - C.c.y) > 0 || dcmp(Y.y - A.y) < 0 || dcmp(Y.y - B.y) > 0) return ret;        ret++;        return ret;    }}const int maxn = 1010;int T, cas = 1, n, tot;double v1, v2, v0, dt, sx, t;double xx, yy, r, h;Point ST, ED;Vector v;struct Seg{    double x1, x2;    Seg(double x1=0, double x2=0) : x1(x1), x2(x2) {}    bool operator < (const Seg &o) const { return x1 > o.x1;}}s[maxn];bool inside(Point p, Point A, Point B, Point C, Circle c){    if (dcmp(Area2(p, A, B) + Area2(p, A, C) + Area2(p, B, C) - Area2(A, B, C)) == 0) return 1;    if (dcmp(Distance(p, c.c) - c.r) <= 0 && dcmp(p.y - c.c.y) <= 0) return 1;    return 0;}int main(){    scanf("%d", &T);    while (T--)    {        scanf("%lf%lf%lf%lf%lf",&v1,&v2,&v0,&dt,&sx);        t = dt + v1*dt/(v2-v1);        v = Vector(-v1, v0);        ST = Point(sx, 0); ED = ST + v*t;        tot = 0;        scanf("%d",&n);        for (int i=1;i<=n;i++)        {            scanf("%lf%lf%lf%lf",&xx,&yy,&r,&h);            Point A = Point(xx, yy+h);            Point B = Point(xx-r, yy); Point C = Point(xx+r, yy);            Circle c = Circle(Point(xx, yy), r);            int cnt = 0, ttmp;            double tmp[10];            Point tmp1, tmp2;            if (OnSegment(A, ST, ED)) tmp[cnt++] = A.x;            if (OnSegment(B, ST, ED)) tmp[cnt++] = B.x;            if (OnSegment(C, ST, ED)) tmp[cnt++] = C.x;            if (SegmentProperIntersection(ST, ED, A, B))                tmp[cnt++] = GetLineIntersection(ST, ED, A, B).x;            if (SegmentProperIntersection(ST, ED, A, C))                tmp[cnt++] = GetLineIntersection(ST, ED, A, C).x;            if ((ttmp = GetLineCircleIntersection(ST, ED, c, tmp1, tmp2)) > 0)            {                tmp[cnt++] = tmp1.x;                if (ttmp == 2) tmp[cnt++] = tmp2.x;            }            if (inside(ST, A, B, C, c)) tmp[cnt++] = ST.x;            if (inside(ED, A, B, C, c)) tmp[cnt++] = ED.x;            if (cnt >= 2)            {                sort(tmp, tmp+cnt);                s[tot++] = Seg(tmp[cnt-1], tmp[0]);            }        }        sort(s, s+tot);        double ans = 0, fst = sx, lst = sx;        for (int i=0;i<tot;i++)        {            if (s[i].x1 < lst)            {                ans += (fst-lst) / v1;                fst = s[i].x1; lst = s[i].x2;            }            else            {                lst = min(lst, s[i].x2);            }        }        ans += (fst - lst) / v1;        printf("Case %d: %.4lf\n", cas++, ans);    }    return 0;}


原创粉丝点击