【计算几何】bzoj1043 [HAOI2008]下落的圆盘

n^2枚举圆盘,用两圆圆心的向量的极角+余弦定理求某个圆覆盖了该圆的哪一段区间(用弧度表示),最后求个区间并。

注意……精度……最好再累计区间的时候,把每个区间的长度减去EPS,防止最后覆盖的总区间超过2PI一点点,使答案为负。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define EPS 0.000000001
#define INF 1000000.0
int n;
const double PI=acos(-1.0);
double rs[1001],xs[1001],ys[1001],ans;
struct Seg
{
	double l,r;
	Seg(){}
	Seg(const double &L,const double &R){l=L; r=R;}
}q[10001];
bool cmp(const Seg &a,const Seg &b)
{
	return fabs(a.l-b.l)<EPS ? a.r<b.r : a.l<b.l;
}
double sqr(const double &x)
{
	return x*x;
}
double dis(double x1,double y1,double x2,double y2)
{
	return sqrt(sqr(x1-x2)+sqr(y1-y2));
}
int main()
{
//	freopen("bzoj1043.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	  scanf("%lf%lf%lf",&rs[i],&xs[i],&ys[i]);
	for(int i=1;i<=n;++i)
	  {
	  	int e=0;
	  	double Lef=2.0*PI;
	  	for(int j=i+1;j<=n;++j)
	  	  {
	  	  	double d=dis(xs[i],ys[i],xs[j],ys[j]);
	  	  	if(d+rs[i]-rs[j]<EPS)
	  	  	  {
	  	  	  	Lef=0.0;
	  	  	  	break;
	  	  	  }
	  	  	else if(d+rs[j]-rs[i]<EPS || rs[i]+rs[j]-d<-EPS)
	  	  	  continue;
//	  	  	double see=(sqr(d)+sqr(rs[i])-sqr(rs[j]))*0.5/d/rs[i];
	  	  	double jiao2=acos((sqr(d)+sqr(rs[i])-sqr(rs[j]))*0.5/d/rs[i]);
	  	  	double jiao1=atan2(ys[j]-ys[i],xs[j]-xs[i]);
	  	  	if(jiao1<-EPS)
	  	  	  jiao1+=(2.0*PI);
	  	  	if(jiao1-jiao2<-EPS)
	  	  	  {
	  	  	  	q[++e]=Seg(0.0,jiao1+jiao2);
	  	  	  	q[++e]=Seg(jiao1-jiao2+2.0*PI,2.0*PI);
	  	  	  }
	  	  	else if(jiao1+jiao2-2.0*PI>EPS)
	  	  	  {
	  	  	  	q[++e]=Seg(jiao1-jiao2,2.0*PI);
	  	  	  	q[++e]=Seg(0.0,jiao1+jiao2-2.0*PI);
	  	  	  }
	  	  	else
	  	  	  q[++e]=Seg(jiao1-jiao2,jiao1+jiao2);
		  }
//		for(int j=e;j;--j)
//		  {
//		  	bool fl=0;
//		  	for(int k=j-1;k;--k)
//		  	  if(!(q[j].l-q[k].r>EPS||q[k].l-q[j].r>EPS))
//		  	    {
//		  	      q[k].l=min(q[j].l,q[k].l);
//		  	      q[k].r=max(q[j].r,q[k].r);
//		  	      fl=1;
//		  	      break;
//		  	    }
//		  	if(!fl)
//		  	  Lef-=(q[j].r-q[j].l);
//		  }
		Seg now=Seg(INF,INF);
		sort(q+1,q+e+1,cmp);
		for(int j=1;j<=e;++j)
		  if(j==e || q[j+1].l-q[j].l>EPS)
		    {
		      if(fabs(now.l-INF)<EPS) now=q[j];
		      else
		        {
		          if(q[j].l-now.r<EPS) now.r=max(now.r,q[j].r);
		          else
				    {
				      Lef-=(now.r-now.l);
				      now=q[j];
				    }
		        }
		    }
		if(fabs(now.l-INF)>=EPS)
		  Lef-=(now.r-now.l);
		if(Lef>EPS)
		  ans+=(Lef*rs[i]);
	  }
	printf("%.3lf\n",ans);
	return 0;
}
posted @ 2016-10-10 23:50  AutSky_JadeK  阅读(166)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト