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\n",ans);
  return 0;
}

原文地址:https://www.cnblogs.com/Zinn/p/10145010.html

时间: 2024-11-20 11:59:38

bzoj 1043 下落的圆盘 —— 求圆心角、圆周长的相关文章

BZOJ 1043 下落的圆盘

Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  Input n ri xi y1 ... rn xn yn Output 最后的周长,保留三位小数 Sample Input 2 1 0 0 1 1 0 Sample Output 10.472 HINT 数据规模 n<=1000 这道题目很好嘴巴,但是写起来有点儿蛋疼. 首先求出每个圆盘被他上面的圆盘覆盖的圆心角的度数α,用(2π-α)*c/2π

BZOJ 1043 HAOI 2008 下落的圆盘 计算几何

题目大意:给出一些圆盘,他们按照时间顺序相互覆盖,问最后的到的图形的可见圆周的周长是多少. 前言:円盘反对!让我们一起团结起来!赶走円盘! 思路:对于每一个圆盘,只要扫描在它后面出现的圆与它交的部分的并,总周长-相交的并就是剩下能看见的圆周的长度,然后累加到答案中. 对于两个圆的交,我们可以用一个有序数对(x,y)以弧度为单位来表示,这样所有的xy都在0~2π区间之内.求角度就利用余弦定理,见下图: ∠EAC就是我们要求的角.由于我们知道|AE|和|EC|分别是两个圆的半径,|AC|是圆心的距离

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

1043: [HAOI2008]下落的圆盘 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1598  Solved: 676[Submit][Status][Discuss] Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  Input 第一行为1个整数n,N<=1000接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标

【BZOJ1043】[HAOI2008]下落的圆盘 几何

[BZOJ1043][HAOI2008]下落的圆盘 Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  Input 第一行为1个整数n,N<=1000接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标. Output 最后的周长,保留三位小数 Sample Input 2 1 0 0 1 1 0 Sample Output 10.472 题解:对于每个圆,我们枚举它后面的

POJ 2546 &amp; ZOJ 1597 Circular Area(求两圆相交的面积 模板)

题目链接: POJ:http://poj.org/problem?id=2546 ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=597 Description Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three di

hdu 3264 Open-air shopping malls 求两圆相交

对每个圆二分半径寻找可行的最小半径,然后取最小的一个半径. 对于两圆相交就只要求到两个扇形,然后减去两个全等三角形就行了. #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> using namespace std; #define pi acos(-1.0) #define eps 1e-8 #define maxn 50 int n; struct point{

BZOJ 3000(Big Number-Stirling公式求n!近似值)

3000: Big Number Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 220  Solved: 62 [Submit][Status] Description 给你两个整数N和K,要求你输出N!的K进制的位数. Input 有多组输入数据,每组输入数据各一行,每行两个数--N,K Output 每行一个数为输出结果. Sample Input 2 5 2 10 10 10 100 200 Sample Output 1 1 7 69 对

【c语言】设圆半径r = 1.5,圆柱高h = 3,求圆周长,圆面积,圆球表面积,圆球体积,圆柱体积

// 设圆半径r = 1.5,圆柱高h = 3,求圆周长,圆面积,圆球表面积,圆球体积,圆柱体积 // 要求:用scanf输入数据,取小数点后两位 #include <stdio.h> int main() { float r,h; float c,s,sq,vq,vz; float pai = 3.1415926; printf("请输入圆半径:"); scanf("%f",&r); printf("请输入圆柱高:"); s

HDU 4667 Building Fence(求凸包的周长)

A - Building Fence Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Description Long long ago, there is a famous farmer named John. He owns a big farm and many cows. There are two kinds of cows on his farm, o