zoukankan      html  css  js  c++  java
  • HDU 4637 Rain on your Fat brother 线段与半圆和线段交 简单题

    题意:

    应该不难读懂。


    做法:

    我们可以把雨滴看做静止不动,然后maze(这题的那个人)就是往左上方运动就可以了,计算出maze能跑到的最远的点,然后就是求起点和终点所构成的线段与每个雨滴交的时间,注意题目说每个雨滴可能会相交,所以我们对于每个雨滴算出相交的区间,然后对这些区间进行合并并且计算答案。


    注意点:

    1.maze有可能一开始就在雨滴里面。

    2.还有maze穿了一部分的雨滴就被追上了。 (竟然没有这种数据)

    3.两线段共线的情况,就是三角形右边的那条边 与 maze的线段共线, 这种情况之下也要细分,但我没判这种情况也AC了,说明没有这种数据,但考虑问题时我们需要把它考虑进去。 (竟然没有这种数据)


    知道以上注意点AC应该不远了,毕竟不是什么难题,我的代码没有写第三种情况。


    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    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);
        }
    } s, e;
    
    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;
        /*			雨滴三角形的三个点标号
         * 				 c
         * 				/_
         * 			       a   b
         */
        void in() {
            scanf("%lf%lf%lf%lf", &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 intersectC() {		//与雨滴的半圆 交 求交点
            point b = s, d = e - s;
            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 < s.x && tp.x + eps > e.x && tp.y - eps < o.y)	//因为是半圆,注意把没用的点判掉
                vec.pb(tp.x);
    
            t = (-B + dlt) / (2 * A);
            tp = b + d * t;
            if (tp.x - eps < s.x && tp.x + eps > e.x && tp.y - eps < o.y)
                vec.pb(tp.x);
    
        }
    
        void intersectT() { //与雨滴的三角形 交 求交点 (水平的线段不算在其中)
            double x;
            if (segSegIntersect(a, c, s, e)) {
                x = intersect(a, c, s, e);
                if (x - eps > e.x && x + eps < s.x)
                    vec.pb(x);
            }
            if (segSegIntersect(c, b, s, e)) {
                x = intersect(c, b, s, e);
                if (x - eps > e.x && x + eps < s.x)
                    vec.pb(x);
            }
        }
    
        void gao() {
    
            vec.clear();
            intersectC();
            intersectT();
            if (inside(s)) vec.pb(s.x);
            if (inside(e)) vec.pb(e.x);
            sort(vec.begin(), vec.end());
            int cnt = unique(vec.begin(), vec.end()) - vec.begin();
            if (cnt >= 2)			//取最大和最小的两个交点  就是被雨滴打到的时间段  的 两端点
                res.pb(mp(vec[0], vec[cnt - 1]));
        }
    } p;
    
    int main() {
        int i, j, cas;
        scanf("%d", &cas);
        for (int ca = 1; ca <= cas; ca++) {
            scanf("%lf%lf%lf%lf%lf%d", &v1, &v2, &v, &t, &x, &n);
            T = v1 * t / (v2 - v1) + t;
            s.x = x;
            s.y = 0;
            e.x = x - v1 * T;
            e.y = v * T;
            ans = 0;
            res.clear();
            for (i = 0; i < n; i++) {
                p.in();
                p.gao();
            }
    
            //对每个时间段去重后计算答案
            sort(res.begin(), res.end());
    
            double r = e.x;
            int SZ = res.size();
            for (i = 0; i < SZ; 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
    ", ca, ans / v1);
        }
        return 0;
    }
    


  • 相关阅读:
    获取文件夹下的所有文件名,并修改某些文件名 Alec
    生成XML文件,并保存到本地文件 Alec
    按Enter键起到Tab键的效果 Alec
    网站底部浮动js Alec
    NET Framework4.0注册 Alec
    从FTP上下载文件到本地 Alec
    生成txt日志操作文件 Alec
    不使用第三个变量,实现两个变量值的交换 Alec
    生成指定位数的回文素数 Alec
    单击gridview某一列弹出详细信息 Alec
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3239001.html
Copyright © 2011-2022 走看看