HDU 4637 Rain on your Fat brother

题意可以归纳为:求一条线段和雨滴的交的总长度。

分析:雨滴和线段的交点可以分为三角形和半圆的交点,注意线段可能会重复, 扫描线判重就可以了。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>

#define FOR(i, n) for(int i = 0; i < n; i++)
#define MEM(array) memset(array, 0, sizeof(array))
#define eps 1e-7
#define INF 1e10
#define PI acos(-1.0)
using namespace std;
inline int sgn(const double &x){return x > eps ? 1 : (x < -eps ? -1 : 0);}
inline double sqr(const double &x){return x * x;}
struct Point{
        double x, y;
        Point(){}
        Point(const double &xx, const double &yy):x(xx), y(yy){}
        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 * (const double &w)const{
            return Point(x * w, y * w);
        }
        Point operator / (const double &w)const{
            return Point(x / w, y / w);
        }
        friend Point operator * (const double &w, const Point &a){
            return Point(a.x * w, a.y * w);
        }
        friend double det(const Point &a, const Point &b){
            return a.x * b.y - a.y * b.x;
        }
        friend double dot(const Point &a, const Point &b){
            return a.x * b.x + a.y * b.y;
        }
        friend double dist(const Point &a, const Point &b){
            return (b - a).len();
        }
        double len()const{
            return sqrt( dot(*this, *this));
        }
        Point norm()const{
            double vLen = len();
            return Point(x / vLen , y / vLen);
        }
        Point rotate(double angle){
            double x1  = x * cos(angle) - y * sin(angle);
            double y1  = x * sin(angle) + y * cos(angle);
            return Point(x1, y1);
        }
        bool operator < (const Point &a)const {
            return sgn(x - a.x) < 0 || (sgn(x  - a.x) == 0 && sgn(y - a.y) > 0);
        }
        bool operator > (const Point &a)const {
            return sgn(x - a.x) > 0 || (sgn(x  - a.x) == 0 && sgn(y - a.y) < 0);
        }
        bool operator == (const Point &a)const {
            return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;
        }
        void in(){
            scanf("%lf %lf", &x, &y);
        }
        void out()const{
            printf("%.4f   %.4f\n", x, y);
        }
};
struct Line{
    Point s, t;
    Line(){}
    Line(const Point &ss, const Point &tt):s(ss), t(tt){}
    friend bool lineParallelLine(const Line &l1, const Line &l2){
        return sgn(det(l1.t - l1.s, l2.t - l2.s)) == 0;
    }
    friend bool isPointOnLine(const Point &a, const Line &line){
        Point va = line.s - a, vb = line.t - a;
        int res1 = sgn(det(va, vb));
        if(res1 != 0)return false;
        return sgn( dot(va, vb) ) <= 0;
    }
    friend double pointDistLine(const Point &p, const Line &line){
        return fabs(det(p - line.s, line.t - line.s)/ (line.t- line.s).len());
    }
    friend Point pointProjLine(const Point &p, const Line &line){
        return line.s + ( line.norm() * dot(p - line.s, line.t - line.s)/ (line.t - line.s).len() );
    }
    friend bool sameSide(const Line &line, const Point &a, const Point &b){
        int res1 = sgn(det( a - line.s, line.t - line.s));
        int res2 = sgn(det( b - line.s, line.t - line.s));
        return res1 * res2 > 0;
    }
    friend vector<Point> lineInsectLine(const Line &l1, const Line &l2){
        vector<Point>res;
        if(lineParallelLine(l1, l2)){
                if( sgn(pointDistLine(l1.s, l2))==0 )res.push_back(l1.s);
                if( sgn(pointDistLine(l1.t, l2))==0 )res.push_back(l1.t);
        }else {
                Point vs = l1.s - l2.s, vl = l2.t - l2.s, vt = l1.t - l2.s;
                double s1 = det(vs, vl), s2 = det(vt, vl);
                res.push_back( (s1 * l1.t - s2 * l1.s)/(s1- s2));
        }
        return res;
    }
    Point norm()const{
        return (t - s).norm();
    }
     Point vec()const{
        return t - s;
    }
    void out()const{
        s.out();
        t.out();
    }
};
int numl;
struct Tri{
    Point a[3];
    Tri(){}
    Tri(const Point &aa, const Point &bb, const Point &cc){
        a[0] = aa; a[1] = bb; a[2] = cc;
    }

    friend vector<Point> triInsectLine(const Tri &tri, const Line &line){
        vector<Point>res, tt;
        for(int i = 0; i < 3; i++){
            Line linet(tri.a[i], tri.a[(i + 1)%3]);
            tt = lineInsectLine(line, linet);
            FOR(j, tt.size()){
                if(isPointOnLine(tt[j], linet))res.push_back(tt[j]);
            }
        }
        sort(res.begin(), res.end());
        int tn = unique(res.begin(), res.end()) - res.begin();
        res.resize(tn);
        return res;
    }
};
struct Cir{
    Point o;
    double r;
    Cir(){}
    Cir(const Point &p, const double &rr):o(p), r(rr){}
    friend vector<Point>  cirInsectLine(const Cir &cir, const Line &line){
        vector<Point>res;
        double dist = pointDistLine(cir.o, line);
        if(dist < cir.r){
            double len = sqrt(sqr(cir.r) - sqr(dist));
            Point re = pointProjLine(cir.o, line);
            Point tt1 = re - (line.norm() * len), tt2 = re + (line.norm() * len);
            if( sgn(tt1.y - cir.o.y) < 0) res.push_back(tt1);
            if( sgn(tt2.y - cir.o.y) < 0) res.push_back(tt2);
        }
        return res;
    }
    void in(){
        o.in();
        scanf("%lf",&r);
    }
};
Point endPoint, srcPoint;
Line mainLine, endLine;
struct Rain{
    Tri tri;
    Cir cir;
    Rain(){}
    friend Line rainInsectLine(const Rain &rain, const Line &line){
        vector <Point>res;
        vector<Point>res1 = triInsectLine(rain.tri, line);
        vector<Point>res2 = cirInsectLine(rain.cir, line);
        Point leftPoint = line.t, rightPoint = line.s;
        FOR(i, res1.size()){
            res.push_back(res1[i]);
        }
        FOR(i, res2.size()){
           res.push_back(res2[i]);
        }
        int len = res.size();
        if(len > 1){
            FOR(i, len){
                if(leftPoint > res[i])leftPoint = res[i];
                if(rightPoint < res[i])rightPoint = res[i];
            }
            if(leftPoint < line.s)leftPoint = line.s;
            if(rightPoint > line.t)rightPoint = line.t;
        }else {
            leftPoint = rightPoint;
        }
        return Line(leftPoint, rightPoint);
    }
    void in(){
        cir.in();
        double h;
        scanf("%lf", &h);
        Point a(cir.o.x - cir.r, cir.o.y), b(cir.o.x + cir.r, cir.o.y), c(cir.o.x, cir.o.y + h);
        tri = Tri(a, b, c);
    }
}rain[11111];
double va, vb, vr,  t, x;
int n;
Point vMain;
void init(){
    srcPoint = Point(x, 0);
    t += t *va/ (vb - va);
    vMain = Point(-va, vr);
    endPoint = srcPoint + vMain * t;
    mainLine = Line(endPoint, srcPoint);
}
struct pointR{
    Point p;
    int type;
    bool operator < (const pointR &a)const {
        return p < a.p;
    }
}pr[11111];
int ca = 0;
double ans = 0;
void solve(){
    ans = 0;
    FOR(i, n){
        Line line = rainInsectLine(rain[i], mainLine);
        pr[i * 2].p = line.s; pr[i * 2].type = 1;
        pr[i * 2 + 1].p = line.t; pr[i * 2 + 1].type = -1;
    }
    int cnt = 0;
    sort(pr, pr + 2 * n);
    FOR(i, 2 * n){
        if(cnt){
            ans += fabs( Line(pr[i -1].p, pr[i].p).vec().len());
        }
        cnt += pr[i].type;
    }
    printf("Case %d: %.4f\n", ++ca, ans / vMain.len());
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%lf %lf %lf %lf %lf", &va, &vb, &vr, &t, &x);
        scanf("%d", &n);
        FOR(i, n){
            rain[i].in();
        }
        init();
        solve();
    }
    return 0;
}
/*
2
1

1 2 1 5 0
1
-4 5 2 2
*/


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值