Everything Has Changed(圆交点模板)
又到了考验板子的时候了,1A就很舒服,挂个all ok的板子
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-8;
int cmp(double x)
{
if(fabs(x)<eps) return 0;
if(x>0) return 1;
return -1;
}
const double pi=acos(-1.0);
inline double sqr(double x)
{
return x*x;
}
struct point
{
double x,y;
point() {};
point(double a,double b):x(a),y(b) {};
void input()
{
scanf("%lf%lf",&x,&y);
}
friend point operator + (const point &a,const point &b)
{
return point(a.x+b.x,a.y+b.y);
}
friend point operator - (const point &a,const point &b)
{
return point(a.x-b.x,a.y-b.y);
}
friend bool operator == (const point &a,const point &b)
{
return cmp(a.x-b.x)==0&&cmp(a.y-b.y)==0;
}
friend point operator * (const point &a,const double &b)
{
return point(a.x*b,a.y*b);
}
friend point operator * (const double &a,const point &b)
{
return point(a*b.x,a*b.y);
}
friend point operator / (const point &a,const double &b)
{
return point(a.x/b,a.y/b);
}
double norm()
{
return sqrt(sqr(x)+sqr(y));
}
};
double det(const point &a,const point &b)
{
return a.x*b.y-a.x*b.y;
}
double dot(const point &a,const point &b)
{
return a.x*b.x+a.y*b.y;
}
double dis(const point &a,const point &b)
{
return (a-b).norm();
}
point rotate_point(const point &p,double A)
{
double tx=p.x,ty=p.y;
return point(tx*cos(A)-ty*sin(A),tx*sin(A)+ty*cos(A));
}
int dcmp(double k)
{
return k<-eps?-1:k>eps?1:0;
}
double cross(const point &a,const point &b)
{
return a.x*b.y-a.y*b.x;
}
double abs(const point &o)
{
return sqrt(dot(o,o));
}
double mysqrt(double n)
{
return sqrt(max(0.0,n));
}
//向量p旋转X角度后的向量,cost,sint为角度X的三角函数值
point rotate(const point &p,double cost,double sint)
{
double x=p.x,y=p.y;
return point(x*cost-y*sint,x*sint+y*cost);
}
//圆A,B的两个交点
pair<point,point> crosspoint(point ap,double ar,point bp,double br)
{
double d=(ap-bp).norm();
double cost=(ar*ar+d*d-br*br)/(2*ar*d);
double sint=sqrt(1.0-cost*cost);
point v=(bp-ap)/(bp-ap).norm()*ar;
return make_pair(ap+rotate(v,cost,-sint),ap+rotate(v,cost,sint));
}
//计算割弧补弧周长
double cal(point a,point b,point c,point d,double R,double r)
{
double C=dis(a,b);
double B=dis(a,c);
double A=dis(b,c);
double anglea=2.0*acos((B*B+C*C-A*A)/(2.0*B*C));
double angleb=2.0*acos((A*A+C*C-B*B)/(2.0*A*C));
return angleb*r-anglea*R;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
double R;
scanf("%d%lf",&n,&R);
point a;
a.x=0,a.y=0;
double ans=2.0*pi*R;
for(int i=0; i<n; i++)
{
double x,y,r;
scanf("%lf%lf%lf",&x,&y,&r);
point bp;
bp.input();
pair<point,point> ins=crosspoint(a,R,bp,r);
double L=sqrt((a.x-bp.x)*(a.x-bp.x)+(a.y-bp.y)*(a.y-bp.y));
if(L<R+r&&L>R-r) ans+=cal(a,bp,ins.first,ins.second,R,r);
else if(L==R-r) ans+=2.0*pi*r;//如果恰好从内部相切,直接加上整个周长
}
printf("%.10f\n",ans);
}
return 0;
}