zoukankan      html  css  js  c++  java
  • hdu4637 计算俩运动对象的时间交

    题:http://acm.hdu.edu.cn/showproblem.php?pid=4637

    参考自:https://www.cnblogs.com/javawebsoa/p/3239001.html

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair <double, double>
    #define mp make_pair
    #define pb push_back
    #define X first
    #define Y second
    const double eps = 1e-8;
    int dcmp(double x) {
        if (fabs(x) < eps)
            return 0;
        return x > eps ? 1 : -1;
    }
    struct point {
        double x, y;
        point() {
    
        }
        point(double x, double y) :
                x(x), y(y) {
        }
        double operator *(const point &t) const {
            return x * t.x + y * t.y;
        }
        point operator -(const point &t) const {
            return point(x - t.x, y - t.y);
        }
        point operator +(const point &t) const {
            return point(x + t.x, y + t.y);
        }
        point operator *(const double &t) const {
            return point(t * x, t * y);
        }
    }sta,ed;
    
    double v1, v2, v, t, x, T;
    double ans;
    int n;
    inline double F(double x) {
        return x * x;
    }
    double cross(const point &o, const point &a, const point &b) {
        return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
    }
    double dis(const point &a, const point &b) {
        return sqrt(F(a.x - b.x) + F(a.y - b.y));
    }
    
    bool segSegIntersect(const point &a, const point &b, const point &l, const point &r) {//两线段相交(不考虑共线)
        return cross(a, b, l) * cross(a, b, r) < eps
                && cross(l, r, a) * cross(l, r, b) < eps;
    }
    
    double intersect(const point &a, const point &b, const point &l, const point &r) {//俩直线求交点的x
        double ret = a.x;
        double t = ((a.x - l.x) * (l.y - r.y) - (a.y - l.y) * (l.x - r.x))
                / ((a.x - b.x) * (l.y - r.y) - (a.y - b.y) * (l.x - r.x));
        return ret + (b.x - a.x) * t;
    }
    
    vector<double> vec; //记录与雨滴的交点
    vector<pii>res;   //记录被雨滴打到的每个时间段
    struct rain {
        point o, a, b, c;
        double r, h;
        void in() {
            cin>>o.x>>o.y>>r>>h;
            ///只记录雨滴的三角形即可 
            a = o, b = o, c = o;
            a.x -= r;
            b.x += r;
            c.y += h;
        }
        bool inside(const point &p) {      //点是否在雨滴里面(包括边界)
            return (dis(o, p) - eps < r && p.y - eps < o.y)
                    || (cross(c, a, p) > -eps && cross(c, b, p) < eps
                            && p.y > o.y + eps);
        }
        void query1(){//与雨滴的半圆 交 求交点
            point b=sta,d=ed-sta;
            double A=d*d;
            double B=(b-o)*d*2;
            double C=(b-o)*(b-o)-r*r;
            double dlt=B*B-4*A*C;
            if(dlt<-eps)return;
            if(dlt<eps)dlt=0;        //消除dlt负数零的情况
            else dlt=sqrt(dlt);
    
            double t=(-B-dlt)/(2*A);
            point tp=b+d*t;
            ///半圆可能的俩个一进一出交点 
            if (tp.x-eps<sta.x&&tp.x+eps>ed.x&&tp.y-eps<o.y)    //因为是半圆,注意把没用的点判掉
                vec.pb(tp.x);
    
            t=(-B+dlt)/(2*A);
            tp=b+d*t;
            if (tp.x-eps<sta.x&&tp.x+eps>ed.x&&tp.y-eps<o.y)
                vec.pb(tp.x);
        }
        void query2(){ //与雨滴的三角形 交 求交点 (水平的线段不算在其中,因为只算进和出,水平线不影响)
            double x;
            if(segSegIntersect(a,c,sta,ed)){
                x=intersect(a,c,sta,ed);
                if(x-eps>ed.x&&x+eps<sta.x)
                    vec.pb(x);
            }
            if(segSegIntersect(c,b,sta,ed)){
                x=intersect(c,b,sta,ed);
                if(x-eps>ed.x&&x+eps<sta.x)
                    vec.pb(x);
            }
        }
        void solve() {
            vec.clear();
            query1();
            query2();
            ///判断起点终点有没有在当前点的范围内 
            if (inside(sta)) vec.pb(sta.x);
            if (inside(ed)) vec.pb(ed.x);
            sort(vec.begin(), vec.end());
            int m=unique(vec.begin(), vec.end()) - vec.begin();
            if(m>=2)//取最大和最小的两个交点就是被雨滴打到的时间段的两端点
                res.pb(mp(vec[0],vec[m-1]));
        }
    }num;
    void init(){
        
    }
    int main() {
        int  cas;
        cin>>cas;
        for (int p=1;p<=cas;p++){
            cin>>v1>>v2>>v>>t>>x>>n;
            T=v1*t/(v2-v1)+t;
            sta.x=x;
            sta.y=0;
            ed.x=x-v1*T;
            ed.y=v*T;
            ans=0;
            res.clear();
            for(int i=0;i<n;i++){
                num.in();
                num.solve();
            }
            sort(res.begin(), res.end());
            double r=ed.x;
            for (int i=0;i<res.size();i++){
                if(res[i].X-eps<r&&r-eps<res[i].Y){
                    ans+=res[i].Y-r;
                    r=res[i].Y;
                }
                else if(r-eps<res[i].X){
                    ans+=res[i].Y-res[i].X;
                    r=res[i].Y;
                } 
            }
            printf("Case %d: %.4f
    ",p,ans/v1);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Head First设计模式读书笔记
    通过FileReference打开本地图片崩溃的解决方法
    Asea——轻量级的AS3模块配置与加载管理库
    AGAL反编译器
    [Stage3D]硬件加速的径向模糊
    C#的timer类问题~!
    c语言中的大数运算模块
    TRACERT命令及用法
    Linux用户和用户组的管理概述
    linux下挂载windows的共享文件目录ftp文件夹到/root/wind目录
  • 原文地址:https://www.cnblogs.com/starve/p/12435852.html
Copyright © 2011-2022 走看看