zoukankan      html  css  js  c++  java
  • bzoj 1043 下落的圆盘 —— 求圆心角、圆周长

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1043

    求出每个圆没被覆盖的长度即可;

    特判包含和相离的情况,注意判包含时 i 包含 j 和 j 包含 i 是不同的情况;

    然后考虑相交,可以算出被覆盖的那段圆弧所对的圆心角,用一个 [0,2π] 的角度区间维护没被覆盖的部分;

    所求的角度是对于一条“基准线”而言的,所以首先要求出圆心连线对于“基准线”的角度,因为知道两个圆心,可以利用 atan2(y,x) 求出 tan(θ) = y/x 对应的 θ

    然后求圆弧的两个端点的角度,发现已知三边,可以用余弦定理;

    求出角度,覆盖区间,最后在 [0,2π] 上找出没被覆盖的区间长度,就能算了。

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    using namespace std;
    typedef double db;
    db const Pi=acos(-1.0),eps=1e-8;
    int const xn=1005;
    int n;
    db ans;
    struct N{db x,y,r;}p[xn];
    struct P{
      db l,r;
      P(db l=0,db r=0):l(l),r(r) {}
      bool operator < (const P &y) const
      {return l<y.l;}
    }v[xn];
    db sqr(db x){return x*x;}
    int dmp(db x){if(fabs(x)<=eps)return 0; return x>eps?1:-1;}
    db dis(N a,N b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
    int main()
    {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)scanf("%lf%lf%lf",&p[i].r,&p[i].x,&p[i].y);
      for(int i=1;i<=n;i++)
        {
          bool fl=0; int cnt=0;
          for(int j=i+1;j<=n;j++)
        {
          db x1=p[i].x,x2=p[j].x,y1=p[i].y,y2=p[j].y,r1=p[i].r,r2=p[j].r,d=dis(p[i],p[j]);
          if(dmp(d+p[i].r-p[j].r)<=0){fl=1; break;}//i in j
          if(dmp(d+p[j].r-p[i].r)<=0||dmp(d-p[i].r-p[j].r)>=0)continue;//j in i
          db fx=atan2(y2-y1,x2-x1);
          db th=acos((sqr(r1)+sqr(d)-sqr(r2))/(2*r1*d));//acos
          db l=fx-th,r=fx+th;
          while(l<0)l+=2*Pi; while(r<0)r+=2*Pi;
          while(l>2*Pi)l-=2*Pi; while(r>2*Pi)r-=2*Pi;
          if(dmp(l-r)<=0)v[++cnt]=P(l,r);
          else v[++cnt]=P(0,r),v[++cnt]=P(l,2*Pi);
        }
          if(fl)continue;//
          sort(v+1,v+cnt+1);
          db mx=0,g=0;
          for(int j=1;j<=cnt;j++)
        {
          if(dmp(v[j].r-mx)<=0)continue;
          if(dmp(v[j].l-mx)>0)g+=v[j].l-mx;
          mx=v[j].r;
        }
          ans+=p[i].r*(g+2*Pi-mx);//
        }
      printf("%.3f
    ",ans);
      return 0;
    }
  • 相关阅读:
    堆栈之链表实现
    队列之数组实现
    堆栈之数组实现
    线性表之循环双链表
    GMAP 集合已修改;可能无法执行枚举操作 错误【正解】(原创)
    大智慧选股公式
    获取股票实时交易数据的方法
    GMAP谷歌地图的纠偏 保密算法
    GMAP 判断一个坐标点是否在不规则多边形内部的算法
    SQL快速操作技巧2_datatable批量更新到数据表
  • 原文地址:https://www.cnblogs.com/Zinn/p/10145010.html
Copyright © 2011-2022 走看看