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*/