题意
分析
两两圆求交点,对每个圆弧按半径抖动。
时间复杂度\(O(T n^2)\)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
template<class T>T read(T&x)
{
return x=read<T>();
}
using namespace std;
typedef long long ll;
co double eps=5e-13;
int dcmp(double x)
{
if(fabs(x)<0)
return 0;
else
return x<0?-1:1;
}
co double PI=acos(-1);
double NormalizeAngle(double rad,double center=PI)
{
return rad-PI*2*floor((rad+PI-center)/(PI*2));
}
struct Point
{
double x,y;
Point(double x=0,double y=0)
:x(x),y(y){}
double angle()
{
return atan2(y,x);
}
};
typedef Point Vector;
Vector operator+(Vector A,Vector B)
{
return Vector(A.x+B.x,A.y+B.y);
}
Vector operator-(Point A,Point 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);
}
double Dot(Vector A,Vector B)
{
return A.x*B.x+A.y*B.y;
}
double Length(Vector A)
{
return sqrt(Dot(A,A));
}
void CircleCircleIntersection(Point c1,double r1,Point c2,double r2,vector<double>&rad)
{
double d=Length(c1-c2);
if(dcmp(d)==0)
return;
if(dcmp(r1+r2-d)<0)
return;
if(dcmp(fabs(r1-r2)-d)>0)
return;
double a=(c2-c1).angle();
double da=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
rad.push_back(NormalizeAngle(a-da));
rad.push_back(NormalizeAngle(a+da));
}
co int N=100;
int n;
Point center[N];
double radius[N];
bool vis[N];
int topmost(Point p)
{
for(int i=n-1;i>=0;--i)
if(dcmp(Length(center[i]-p)-radius[i])<0)
return i;
return -1;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
while(read(n))
{
for(int i=0;i<n;++i)
scanf("%lf %lf %lf",¢er[i].x,¢er[i].y,&radius[i]);
fill(vis,vis+n,0);
for(int i=0;i<n;++i)
{
vector<double>rad;
rad.push_back(0);
rad.push_back(PI*2);
for(int j=0;j<n;++j)
CircleCircleIntersection(center[i],radius[i],center[j],radius[j],rad);
sort(rad.begin(),rad.end());
for(int j=0;j<rad.size();++j)
{
double mid=(rad[j]+rad[j+1])/2;
for(int side=-1;side<=1;side+=2)
{
double r2=radius[i]-side*eps;
int t=topmost(Point(center[i].x+cos(mid)*r2,center[i].y+sin(mid)*r2));
if(t>=0)
vis[t]=1;
}
}
}
int ans=0;
for(int i=0;i<n;++i)
if(vis[i])
++ans;
printf("%d\n",ans);
}
return 0;
}