腊鸡题目。
我们考虑倒着加入圆盘,考虑每一个圆被之后覆盖的弧的总长度。
首先需要把包含的情况去掉。
然后用解析几何算出相交的弧的位置。
然后求一个交。
然后把剩下的结果加入答案中。
写了一下午,发现cos值可能大于1,不能用acos函数计算。
QAQ
#include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define eps 1e-8 #define sqr(x) x*x #define ll long long #define mp make_pair const double pi=acos(-1.0); struct Vector{ double x,y; void print() { printf("Vector -> (%.3f,%.3f) ",x,y); } }; struct Point{ double x,y; void print() { printf("Point . (%.3f,%.3f) ",x,y); } }; Vector operator + (Vector a,Vector b) {Vector ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;} Vector operator - (Vector a,Vector b) {Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;} Point operator + (Point a,Vector b) {Point ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;} Vector operator - (Point a,Point b) {Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;} Vector operator * (Vector a,double b) {Vector ret;ret.x=a.x*b;ret.y=a.y*b;return ret;} double operator * (Vector a,Vector b) {return a.x*b.y-a.y*b.x;} Vector Turn(Vector a,double b) { Vector ret; ret.x=a.x*cos(b)-a.y*sin(b); ret.y=a.x*sin(b)+a.y*cos(b); return ret; } int n; struct Circle{ double x,y,r; void print() { printf("Circle (%.3f,%.3f) r = %.3f ",x,y,r); } }a[1005]; double dst(double x1,double y1,double x2,double y2) {return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));} int dcmp(double x) { if (x>eps) return 1; if (fabs(x)<eps) return 0; return -1; } bool in(Circle a,Circle b) { if (dcmp(dst(a.x,a.y,b.x,b.y)-(b.r-a.r))<=0) return true; return false; } struct Cut_Cir{ double l,r; void print() { printf("Ang (%.3f,%.3f) ",l,r); } }sta[1000005]; int top=0; double nege(double x) { if (dcmp(x)==-1) x+=2*pi; while (dcmp(x-2*pi)>=0) x-=2*pi; return x; } void Cut(int pos) { top=0; double dist; Vector v0,v1,v2; F(i,pos+1,n) if ((dist=dst(a[pos].x,a[pos].y,a[i].x,a[i].y))<a[pos].r+a[i].r) { double ang; ang=(sqr(a[pos].r)+sqr(dist)-sqr(a[i].r))/(2*a[pos].r*dist); if (ang>1.0) continue; ang=acos(ang); v0.x=a[i].x-a[pos].x;v0.y=a[i].y-a[pos].y; v0=v0*(1.0/sqrt(sqr(v0.x)+sqr(v0.y))*a[pos].r); v1=Turn(v0,ang); v2=Turn(v0,-ang); double t1=atan2(v1.y,v1.x),t2=atan2(v2.y,v2.x); t1+=pi;t2+=pi; while (t1>2*pi) t1-=2*pi; while (t2>2*pi) t2-=2*pi; if (t1<t2) { ++top; sta[top].l=0; sta[top].r=t1; ++top; sta[top].l=t2; sta[top].r=2*pi; } else { ++top; sta[top].l=t2; sta[top].r=t1; } } } double C(Circle a) {return a.r*2*pi;} bool cmp2(Cut_Cir a,Cut_Cir b) {return a.l<b.l;} double cal(double r) { sort(sta+1,sta+top+1,cmp2); double now=0,ret=0; F(i,1,top) { now=max(now,sta[i].l); ret+=max(0.0,sta[i].r-now); now=max(now,sta[i].r); } return ret*r; } double ans=0; int main() { scanf("%d",&n); F(i,1,n) scanf("%lf%lf%lf",&a[i].r,&a[i].x,&a[i].y); F(i,1,n) { int flag=1; F(j,i+1,n) if (in(a[i],a[j])) flag=0; if (!flag) continue; Cut(i); ans+=C(a[i]); ans-=cal(a[i].r); } printf("%.3f ",ans); }