HDU 4637 Rain on your Fat brother

题意:和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 second
using 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值