zoukankan      html  css  js  c++  java
  • 【计算几何】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
    ",ans);
    	return 0;
    }
  • 相关阅读:
    在MAC系统的eclipse里打开android sdk manager
    在MAC上搭建eclipse+android开发环境以及eclipse的svn插件的安装
    C语言入门
    变量和数据类型
    兼容 FF&IE 的替换鼠标选择文字方法(转载)
    JavaScript 中在光标处插入添加文本标签节点 详细方法
    jquery获取鼠标位置
    转:javascript Range对象跨浏览器常用操作
    日省三思
    jQuery强大的jQuery选择器 (详解)[转]
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/5947751.html
Copyright © 2011-2022 走看看