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

下落的圆盘

Time Limit: 10 Sec  Memory Limit: 162 MB
[Submit][Status][Discuss]

Description

  有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。

  看下面这副图, 所有的红色线条的总长度即为所求。

  

Input

  第一行为1个整数n
  接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标.

Output

  最后的周长,保留三位小数

Sample Input

  2
  1 0 0
  1 1 0

Sample Output

  10.472

HINT

  n <= 1000

Solution

  显然是一道计算几何题。

  考虑一个圆对于答案的贡献,显然是这个圆的周长 - 后面的圆把它覆盖掉的周长的并。那么我们就考虑怎么求这个并。

  先考虑怎样记录下一个答案,显然直接扣掉单个圆对它的覆盖不可行的,要减去重叠的情况

  既然边不可行,我们就用角度。显然,若我们求出 两圆交点的角度 即可解决这题。

  我们考虑求圆A被圆B覆盖的角度:现在我们有两个圆的半径、圆心距。我们就可以得到 圆A与圆B圆心连线 圆A半径 的夹角。

  我们也可以知道 圆A与圆B圆心连线 x轴的夹角

  这样的话,就可以把单个圆对于它的贡献记录里面,最后扫一遍求一下剩余的角度乘上R就是它对于答案的贡献了。

Code

 

 1 #include<iostream>    
 2 #include<string>    
 3 #include<algorithm>    
 4 #include<cstdio>    
 5 #include<cstring>    
 6 #include<cstdlib>
 7 #include<cmath>
 8 #include<queue>
 9 using namespace std;  
10 typedef unsigned long long s64;
11 
12 const int ONE = 1000005;
13 const double pi = acos(-1.0);
14 
15 int n;
16 struct power
17 {
18         double x, y, r;
19 }a[ONE];
20 
21 struct circle
22 {
23         double a, b;
24 }stk[ONE];
25 int top;
26 
27 double Ans;
28 
29 bool cmp(const circle &a, const circle &b)
30 {
31         if(a.a != b.a) return a.a < b.a;
32         return a.b < b.b;
33 }
34 
35 int get()
36 { 
37         int res,Q=1;    char c;
38         while( (c=getchar())<48 || c>57)
39         if(c=='-')Q=-1;
40         if(Q) res=c-48; 
41         while((c=getchar())>=48 && c<=57) 
42         res=res*10+c-48; 
43         return res*Q; 
44 }
45 
46 double sqr(double x) {return x * x;}
47 double dist(power a, power b) {return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
48 
49 double Calc(power a, power b)
50 {
51         double A = a.r, B = b.r, C = dist(a, b);
52         double cosB = (sqr(A) + sqr(C) - sqr(B)) / (2 * A * C);
53         double angle = atan2(a.x - b.x, a.y - b.y), add = acos(cosB);
54         stk[++top] = (circle){angle - add, angle + add};
55 }
56 
57 double init(power a, power b) {return a.r + dist(a, b) <= b.r;}
58 double sect(power a, power b) {return fabs(a.r - b.r) < dist(a, b) && dist(a, b) < a.r + b.r;}
59 
60 double Deal(int id)
61 {
62         top = 0;
63         for(int i = id+1; i <= n; i++)
64             if(init(a[id], a[i])) return 0;
65         
66         for(int i = id+1; i <= n; i++)
67             if(sect(a[id], a[i])) Calc(a[id], a[i]);
68         
69         for(int i = 1; i <= top; i++)
70         {
71             while(stk[i].a < 0) stk[i].a += 2 * pi;
72             while(stk[i].b < 0) stk[i].b += 2 * pi;
73             if(stk[i].a > stk[i].b) stk[++top] = (circle){0, stk[i].b}, stk[i].b = 2*pi;
74         }
75         
76         sort(stk + 1, stk + top + 1, cmp);
77         double last = 0.0, sum = 0.0;
78         for(int i = 1; i <= top; i++)
79             if(stk[i].a > last) sum += stk[i].a - last, last = stk[i].b;
80             else last = max(last, stk[i].b);
81         
82         sum += 2 * pi - last;
83         return a[id].r * sum;
84 }
85 
86 int main()
87 {
88         n = get();
89         for(int i = 1; i <= n; i++)
90             scanf("%lf %lf %lf", &a[i].r, &a[i].x, &a[i].y);
91         for(int i = 1; i <= n; i++)
92             Ans += Deal(i);
93         printf("%.3lf", Ans);
94 }
View Code

 

转载于:https://www.cnblogs.com/BearChild/p/7280763.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
### 回答1: bzoj作为一个计算机竞赛的在线评测系统,不仅可以提供大量的题目供程序员练习和学习,还可以帮助程序员提升算法和编程能力。为了更好地利用bzoj进行题目的学习和刷题,制定一个bzoj做题计划是非常有必要的。 首先,我们需要合理安排时间,每天留出一定的时间来做bzoj的题目。可以根据自己的时间安排,每天挑选适量的题目进行解答。可以先从难度较低的题目开始,逐渐提高难度,这样既能巩固基础知识,又能挑战自己的思维能力。 其次,要有一个计划和目标。可以规划一个每周或每月的题目数量目标,以及每个阶段要学习和掌握的算法知识点。可以根据bzoj的题目分类,如动态规划、图论、贪心算法等,结合自己的实际情况,有针对性地选择题目进行学习。 此外,要充分利用bzoj提供的资源。bzoj网站上有很多高质量的题解和优秀的解题代码,可以参考和学习。还有相关的讨论区,可以与其他程序员交流和讨论,共同进步。 最后,要坚持并保持思考。做题不是单纯为了刷数量,更重要的是学会思考和总结。遇到难题时,要有耐心,多思考,多尝试不同的解法。即使不能一次性解出来,也要学会思考和分析解题过程,以及可能出现的错误和优化。 总之,bzoj做题计划的关键在于合理安排时间、制定目标、利用资源、坚持思考。通过有计划的刷题,可以提高算法和编程能力,并培养解决问题的思维习惯,在计算机竞赛中取得更好的成绩。 ### 回答2: bzoj做题计划是指在bzoj这个在线测评系统上制定一套学习和刷题的计划,并且将计划记录在excel表格中。该计划主要包括以下几个方面的内容。 首先是学习目标的设定。通过分析自己的水平和知识缺口,可以设定一个合理的目标,比如每天解决一定数量的题目或者提高特定的算法掌握程度。 其次是题目选择的策略。在excel表格中可以记录下自己选择的题目编号、题目类型和难度等信息。可以根据题目的类型和难度来安排每天的刷题计划,确保自己可以逐步提高技巧和解题能力。 然后是学习进度的记录和管理。将每天的完成情况记录在excel表格中,可以清晰地看到自己的学习进度和任务完成情况。可以使用图表等功能来对学习进度进行可视化展示,更好地管理自己的学习计划。 同时,可以在excel表格的备注栏中记录下每道题目的解题思路、关键点和需要复习的知识点等信息。这样可以方便自己回顾和总结,巩固所学的知识。 最后,可以将excel表格与其他相关资料进行整合,比如算法教材、题目解析和学习笔记等。这样可以形成一个完整的学习档案,方便自己进行系统的学习和复习。 总之,bzoj做题计划excel的制定和记录可以帮助我们更加有条理和高效地进行学习和刷题。通过合理安排学习目标和题目选择策略,记录学习进度和思路,并整合其他学习资料,我们可以提高自己的解题能力,并在bzoj上取得更好的成绩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值