HDU4637 Rain on your Fat brother

任意門: 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章