Crazed Boar(平面几何 象限角度区间)

https://vjudge.net/problem/Kattis-crazedboar

题意:

给n个圆的位置的半径,原点有个猪给出半径,会往随机方向移动d单位,问不会碰撞的概率。

解析:

dis表示圆心距离,rsum表示半径和

分为4种:

直接接触,dis<rsum
在这里插入图片描述
无影响,d+rsum<dis

在这里插入图片描述
跑完d后还能接触,d<sqrt(dis*dis-rsum*rsum),角度使用acos算出
在这里插入图片描述

跑完d之前接触,d>sqrt(dis*dis-rsum*rsum),角度使用asin算出
在这里插入图片描述

圆心之间的向量的角度,加减夹角角度,就得到了不能跑的方向区间。最后归到0~2pi,排序后跑一遍即可。

代码:

扫描二维码关注公众号,回复: 10467037 查看本文章
/*
 *  Author : Jk_Chen
 *    Date : 2020-03-08-13.29.25
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define F double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=1e4+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

F eps=1e-9;
const F pi=acos(-1);

struct point{
    F x,y;
    point(){}
    point(F x,F y):x(x),y(y){}
};
typedef point Vector;
typedef point Point;
Vector operator + (Vector a, Vector b){//向量加法
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p){//向量数乘
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p){//向量数除
    return Vector(a.x / p, a.y / p);
}
int dcmp(double x){//精度三态函数(>0,<0,=0)
    if (fabs(x) < eps)return 0;
    else if (x > 0)return 1;
    return -1;
}
bool operator == (const Point &a, const Point &b){//向量相等
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Dot(Vector a, Vector b){//内积
    return a.x*b.x + a.y*b.y;
}
double Length(Vector a){//模
    return sqrt(Dot(a, a));
}
double Angle(Vector a, Vector b){//夹角,弧度制
    return acos(Dot(a, b) / Length(a) / Length(b));
}
double Cross(Vector a, Vector b){//外积
    return a.x*b.y - a.y*b.x;
}
Vector Rotate(Vector a, double rad){//逆时针旋转
    return Vector(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad) + a.y*cos(rad));
}
double Distance(Point a, Point b){//两点间距离
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
double Area(Point a, Point b, Point c){//三角形面积
    return fabs(Cross(b - a, c - a) / 2);
}
bool Intersect(Point a, Point b, Point c, Point d){//线段相交(不包括端点)
    double t1 = Cross(c - a, d - a)*Cross(c - b, d - b);
    double t2 = Cross(a - c, b - c)*Cross(a - d, b - d);
    return dcmp(t1) < 0 && dcmp(t2) < 0;
}
bool StrictIntersect(Point a, Point b, Point c, Point d){ //线段相交(包括端点)
    return
        dcmp(max(a.x, b.x) - min(c.x, d.x)) >= 0
        && dcmp(max(c.x, d.x) - min(a.x, b.x)) >= 0
        && dcmp(max(a.y, b.y) - min(c.y, d.y)) >= 0
        && dcmp(max(c.y, d.y) - min(a.y, b.y)) >= 0
        && dcmp(Cross(c - a, d - a)*Cross(c - b, d - b)) <= 0
        && dcmp(Cross(a - c, b - c)*Cross(a - d, b - d)) <= 0;
}
double DistanceToLine(Point A, Point M, Point N){//点A到直线MN的距离,Error:MN=0
    return fabs(Cross(A - M, A - N) / Distance(M, N));
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){//两直线的交点
    Vector u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}

struct Circle{
    Point c;
    double r;
    Point gpoint(double a){//基于圆心角求圆上一点坐标
        return Point(c.x + cos(a)*r, c.y + sin(a)*r);
    }
}C[maxn],O;
double Angle(Vector v1){
    if (v1.y >= 0)return Angle(v1, Vector(1.0, 0.0));
    else return 2 * pi - Angle(v1, Vector(1.0, 0.0));
}


struct node{
    double l,r;
    bool operator<(const node &A)const{
        return dcmp(l-A.l)<0||dcmp(l-A.l)==0&&dcmp(r-A.r)<0;
    }
};
vector<node>V;
void Insert(double l,double r){
//    debug(l<<' '<<r);
    while(r>=2*pi)l-=2*pi,r-=2*pi;
    while(l<0)l+=2*pi,r+=2*pi;
    if(r<=2*pi)
        V.pb({l,r});
    else{
        V.pb({l,2*pi});
        V.pb({0,r-2*pi});
    }
}

int main(){
//    cout<<Angle(Vector(1,0))<<endl;
//    cout<<asin(sqrt(2.0)/2)<<endl;
    int n=rd;
    rep(i,1,n){
        scanf("%lf%lf%lf",&C[i].c.x,&C[i].c.y,&C[i].r);
    }
    point O={0,0};
    double R;
    double D;
    scanf("%lf%lf",&R,&D);
    rep(i,1,n){
        // 加入禁区<pi
        double Dis=Distance(O,C[i].c),Rsum=R+C[i].r,ANG=Angle(C[i].c);

        if(dcmp(Dis-Rsum)<0)return 0*printf("0\n");
        if(D+Rsum<=Dis)continue;
        double lim=sqrt(Dis*Dis-Rsum*Rsum);
        if(D<=lim){
            double ang=acos((D*D+Dis*Dis-Rsum*Rsum)/(2.0*D*Dis));
            double l=ANG-ang,r=ANG+ang;
            Insert(l,r);
        }
        else{
            double ang=asin(Rsum/Dis);
            double l=ANG-ang,r=ANG+ang;
            Insert(l,r);
        }
    }
    sort(V.begin(),V.end());
    double jin=0;
    double l=0,r=0;
    for(auto P:V){
//        debug(P.l<<' '<<P.r);
        if(P.l<=r)r=max(r,P.r);
        else{
            jin+=r-l;
            l=P.l,r=P.r;
        }
    }
    jin+=r-l;
    printf("%.10f\n",(2*pi-jin)/(2*pi));
    return 0;
}

/*_________________________________________________________end*/
发布了773 篇原创文章 · 获赞 345 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104738432