HDU 4637 Rain on your Fat brother

来源:互联网 发布:荣耀机顶盒直播软件 编辑:程序博客网 时间:2024/05/24 04:17

题意:和Maze在(x,0)位置吵架,Maze在0时刻离开,t时刻开始下雨,雨的速度都为v。Maze的速度为v1,Fat Brother的速度为v2,Fat Brother 从t时刻开始从(x,0)开始追赶Maze给她送伞,求Maze在雨中的时间。雨的竖直下落,且下落位置给出,雨可以看作是等腰三角形和半圆的组合体。

解法:容易计算出Maze在雨中的时间,把雨当成参考系,Maze的路径就是一条线段,求线段和雨的交点即可。求交点分成两部分,一是求三角形和线段的交点,二是求半圆和线段的交点。线段的端点可能在雨内部,要判断这种情况。雨滴可能会重合,所以要先求出对于每滴雨的进入时间和离开时间,之后再扫一边防止重复。


//Time:140MS//Memory:356K#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cmath>#include <vector>#define FI first#define SE secondusing namespace std;const double EPS = 1e-8;const double PI = acos(-1.0);const int MAXN = 1005;inline int dcmp(double x){    if(fabs(x)<EPS) return 0;    return x<0? -1:1;}struct Point{    double x,y;    Point(){}    Point(double a,double b):x(a),y(b){}    Point operator+(const Point &a)const{return Point(x+a.x,y+a.y);}    Point operator-(const Point &a)const{return Point(x-a.x,y-a.y);}    Point operator*(double a)const{return Point(x*a,y*a);}    bool operator < (const Point &a)const    {        return dcmp(x-a.x)<0||(dcmp(x-a.x)==0&&dcmp(y-a.y)<0);    }    bool operator ==(const Point &a)const    {        return dcmp(x-a.x)==0&&dcmp(y-a.y)==0;    }    void input(){scanf("%lf%lf",&x,&y);}    void output(){printf("%.4f %.4f\n",x,y);}};typedef Point Vector;struct Circle{    Point o;    double r;    Circle(){}    Circle(Point a,double b):o(a),r(b){}    Point point(double a)    {        return Point(o.x+cos(a)*r,o.y+sin(a)*r);    }};struct Rain{    double x,y,r,h;    Point a,b,c;    void input()    {        scanf("%lf%lf%lf%lf",&x,&y,&r,&h);        a = Point(x,y+h);        b = Point(x-r,y);        c = Point(x+r,y);    }}rain;pair<double,double> ans[3005];int an;double cross(Vector a,Vector b){    return a.x*b.y-a.y*b.x;}double dot(Vector a,Vector b){    return a.x*b.x+a.y*b.y;}double sqr(double x){    return x*x;}double length(Vector a){    return sqrt(dot(a,a));}double dist(Point a,Point b){    return length(a-b);}bool onseg(Point p,Point a,Point b){    //return dcmp(cross(a-p,b-p))==0&&dcmp(dot(a-p,b-p))<=0;    return dcmp(dist(a, p) + dist(p, b) - dist(a, b)) == 0;}bool ispinter(Point a, Point b, Point c, Point d){    double c1 = cross(b-a,c-a),c2 = cross(b-a,d-a),           c3 = cross(d-c,a-c),c4 = cross(d-c,b-c);    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;}bool isinter(Point s1, Point e1, Point s2, Point e2){    if( min(s1.x, e1.x) <= max(s2.x, e2.x) &&        min(s1.y, e1.y) <= max(s2.y, e2.y) &&        min(s2.x, e2.x) <= max(s1.x, e1.x) &&        min(s2.y, e2.y) <= max(s1.y, e1.y) &&        dcmp(cross(s2-s1,e2-s1))*dcmp(cross(s2-e1,e2-e1))<=0&&        dcmp(cross(s1-s2,e1-s2))*dcmp(cross(s1-e2,e1-e2))<=0)        return true;    return false;}Point getinter(Point a,Vector aa,Point b,Vector bb){    Vector u = a-b;    double t = cross(bb,u)/cross(aa,bb);    return a+aa*t;}int inter_c_seg(Circle c,Point a, Point b, vector<Point>& sol){    Vector v = b-a;    double A = sqr(v.x)+sqr(v.y);    double B = 2*(v.x*(a.x-c.o.x)+v.y*(a.y-c.o.y));    double C = sqr(a.x-c.o.x)+sqr(a.y-c.o.y)-sqr(c.r);    double delta = sqr(B)-4*A*C;    Point p1,p2;    if(dcmp(delta)<0) return 0;    double k1 = (-B-sqrt(delta))/(2*A);    double k2 = (-B+sqrt(delta))/(2*A);    p1 = a+v*k1;    p2 = a+v*k2;    if(dcmp(c.o.y-p1.y)>=0&&onseg(p1,a,b))        sol.push_back(p1);    if(dcmp(c.o.y-p2.y)>=0&&onseg(p2,a,b))        sol.push_back(p2);    return sol.size();}double area(Point a,Point b,Point c){    return fabs(cross(a-c,b-c))/2;}bool inrain(Point p){    if(dcmp(dist(p,Point(rain.x,rain.y))-rain.r)<=0&&dcmp(p.y-rain.y)<=0) return 1;    if(dcmp(area(rain.a,rain.b,rain.c)-area(rain.a,rain.b,p)            -area(rain.a,rain.c,p)-area(rain.b,rain.c,p))==0) return 1;    return 0;}void solve(Point s,Point e){    vector<Point> vec;    vec.clear();    if(isinter(rain.a,rain.b,s,e))        vec.push_back(getinter(rain.a,rain.b-rain.a,s,s-e));    if(isinter(rain.a,rain.c,s,e))        vec.push_back(getinter(rain.a,rain.c-rain.a,s,s-e));    inter_c_seg(Circle(Point(rain.x,rain.y),rain.r),s,e,vec);    if(inrain(s)) vec.push_back(s);    if(inrain(e)) vec.push_back(e);    sort(vec.begin(),vec.end());    unique(vec.begin(),vec.end());    if(vec.size()>1)    {        double t1 = length(vec[1]-s),t2 = length(vec[0]-s);        if(dcmp(t1-t2)>0) swap(t1,t2);        ans[an++] = make_pair(t1,t2);    }}int main(){    //freopen("/home/qitaishui/code/in.txt","r",stdin);    int cas;    double v1,v2,v,t,x;    Point s,e;    int n;    scanf("%d",&cas);    for(int ca = 1; ca <= cas; ca++)    {        scanf("%lf%lf%lf%lf%lf",&v1,&v2,&v,&t,&x);        t = t+t*v1/(v2-v1);        s = Point(x,0);        e = s+Point(-v1,v)*t;        scanf("%d",&n);        an = 0;        for(int i = 0; i < n; i++)        {            rain.input();            solve(s,e);        }        sort(ans,ans+an);        int c=0;        double sum=0;        while(c<an)        {            double se = ans[c].SE;            double fi = ans[c].FI;            c++;            while(c<an&&dcmp(se-ans[c].FI)>=0)            {                se=max(se,ans[c].SE);                c++;            }            sum+=se-fi;        }        sum/=sqrt(v1*v1+v*v);        printf("Case %d: %.4f\n",ca,sum+EPS);    }    return 0;}