记录编号 214805 评测结果 AAAAAAAAAA
题目名称 [HAOI 2008]下落的圆盘 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.143 s
提交时间 2015-12-18 11:05:48 内存使用 0.43 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef double LL;
#define sqr(x) ((x)*(x))
const int SIZEN=5010;
const double PI=acos(-1.0);
int N;
LL X[SIZEN],Y[SIZEN],R[SIZEN];
void add_interval(vector<pair<double,int> > &a,double l,double r){
	//规定极角从-PI到PI 
	if(r>PI){
		a.push_back(make_pair(l,1));
		a.push_back(make_pair(PI,-1));
		a.push_back(make_pair(-PI,1));
		a.push_back(make_pair(r-2*PI,-1));
	}
	else if(l<=-PI){
		a.push_back(make_pair(l+2*PI,1));
		a.push_back(make_pair(PI,-1));
		a.push_back(make_pair(-PI,1));
		a.push_back(make_pair(r,-1));
	}
	else{
		a.push_back(make_pair(l,1));
		a.push_back(make_pair(r,-1));
	}
}
double calc(int i){//计算i号圆的贡献长度 
	vector<pair<double,int> > cov;
	for(int j=i+1;j<=N;j++){
		LL dis=sqr(X[i]-X[j])+sqr(Y[i]-Y[j]);
		if(sqr(R[i]-R[j])>=dis&&R[j]>=R[i]) return 0;//被j完全盖住
		if(sqr(R[i]+R[j])<=dis||sqr(R[i]-R[j])>=dis) continue;//相离,或i盖住了j,则不予理会j 
		double c=atan2(Y[j]-Y[i],X[j]-X[i]);
		//用余弦定理,过两圆心及两圆的交点作三角形 
		double a=acos((sqr(R[i])+dis-sqr(R[j]))/(2*R[i]*sqrt(1.0*dis)));
		add_interval(cov,c-a,c+a);
	}
	double ans=2*PI;
	sort(cov.begin(),cov.end());
	int cnt=0;double nowl;
	for(int i=0;i<cov.size();i++){
		if(cov[i].second==1){
			if(!cnt) nowl=cov[i].first;
			cnt++;
		}
		else if(cov[i].second==-1){
			cnt--;
			if(!cnt) ans-=cov[i].first-nowl;
		}
	}
	return ans*R[i];
}
void work(void){
	double ans=0;
	for(int i=1;i<=N;i++) ans+=calc(i);
	printf("%.03lf\n",ans);
}
void read(void){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%lf%lf%lf",&R[i],&X[i],&Y[i]);
	}
}
int main(void){
	freopen("disc.in","r",stdin);
	freopen("disc.out","w",stdout);
	read();
	work();
	return 0;
}