记录编号 378701 评测结果 AAAAAAAAAA
题目名称 [HAOI 2008]下落的圆盘 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.170 s
提交时间 2017-03-04 17:50:04 内存使用 4.10 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
typedef pair<db,db> pr;
const int N=1e5+10;
const db pi=acos(-1.0);
int n;db x[N],y[N],r[N];
pr p[N];
db sqr(db x){return x*x;}
int main()
{
	freopen("disc.in","r",stdin);
	freopen("disc.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
	db ans=0;
	for (int i=1;i<=n;i++){
		int cnt=0;db now=0;
		for (int j=i+1;j<=n;j++){
			db d=sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
			if (d>r[i]+r[j]) continue;
			if (d<r[j]-r[i]) goto end;
			db alpha=atan2(y[j]-y[i],x[j]-x[i])+pi;
			//余弦定理 
			db k=(sqr(r[i])+sqr(d)-sqr(r[j]))/(2*r[i]*d);
			if (k>1) k=1;
			if (k<-1) k=-1;
			db phi=acos(k);
			if (alpha<phi){
				p[++cnt]=pr(0,alpha+phi);
				p[++cnt]=pr(alpha-phi+2*pi,2*pi);
			}
			else if (alpha+phi>2*pi){
				p[++cnt]=pr(0,alpha+phi-2*pi);
				p[++cnt]=pr(alpha-phi,2*pi);
			}
			else p[++cnt]=pr(alpha-phi,alpha+phi);
		}
		sort(p+1,p+cnt+1);
		for (int j=1;j<=cnt;j++){
			if (now<p[j].first) ans+=r[i]*(p[j].first-now);
			now=max(now,p[j].second);
		}
		ans+=r[i]*(2*pi-now);
		end:;
	}
	printf("%.3lf\n",ans);
	return 0;
}