[Codeforces Round #357 DIV2E (CF681E)] Runaway to a Shadow

题意

平面给出一个圆 O ,同时给出另外n个圆,询问一个蟑螂从圆心 O 沿半径出发,在圆O内可以走到其他圆的概率。

题解

计算几何,用了三角函数,用了余弦定理,难点在精度问题,需要处理好细节。

代码

/// by ztx

#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>

#define  sqr(x)  ((x)*(x))
#define  pb      push_back
#define  mkpr    std::make_pair

typedef double lf;
typedef std::pair<lf,lf> PLF;

const lf eps = 1E-9;
const lf PI = acos(-1.0);

inline lf dist2(lf x1,lf y1,lf x2,lf y2) { return sqr(x1-x2)+sqr(y1-y2); }

std::vector<PLF> a;
std::vector<PLF>::iterator it;

int main() {
    int x0, y0, v, T, n, x, y, r;
    lf R, d, ang, angM, angL, angR, last, ans;
    scanf("%d%d%d%d%d", &x0, &y0, &v, &T, &n);
    R = (lf)v * T;
    while (n --> 0) {
        scanf("%d%d%d", &x, &y, &r);
        d = dist2(x,y,x0,y0);
        if (d < 1.0 * r * r + eps) {
            printf("%.11f", 1.0);
            goto END;
        }
        d = sqrt(d);
        if (R+r < d-eps) continue;
        angM = atan2(y-y0,x-x0);
        if (angM < 0) angM += 2*PI;
        if (sqrt(d*d-1.0*r*r) < R+eps) ang = asin(r / d);
        else ang = acos((d*d+R*R-1.0*r*r) / (2*d*R));
        angL = angM-ang, angR = angM+ang;
        if (angL < 0) {
            a.pb(mkpr(angL+2*PI,1)), a.pb(mkpr(2*PI,-1));
            a.pb(mkpr(0,1)), a.pb(mkpr(angR,-1));
        } else if (angR > 2*PI) {
            a.pb(mkpr(angL,1)), a.pb(mkpr(2*PI,-1));
            a.pb(mkpr(0,1)), a.pb(mkpr(angR-2*PI,-1));
        } else {
            a.pb(mkpr(angL,1)), a.pb(mkpr(angR,-1));
        }
    }
    std::sort(a.begin(),a.end());
    for (last = ans = x = 0, it = a.begin(); it != a.end(); it ++ ) {
        if (x > 0) ans += it->first-last;
        x += it->second;
        last = it->first;
    }
    printf("%.11f\n", ans/(2*PI));
    END:;
    getchar(),getchar();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值