http://www.lydsy.com/JudgeOnline/problem.php?id=1043

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

————————————————————————————————

代码借(抄)鉴(袭)于:http://blog.csdn.net/Vmurder/article/details/46564199

首先我们通过枚举判断两圆的关系:后全覆盖先,先全覆盖后,后和先相交,后和先相离。

显然2和4是没有影响的,而1相当于将先圆干掉了(因为它不再对答案有贡献了)

所以重点在3情况上。

我们弧长公式有:L=角(弧度制)*半径(R)。

所以我们可以用弧度制来表示当前圆被覆盖的部分,即可求出弧长。

基本上高中数学知识即可解决,这里配一张图:

我们这里让a圆覆盖b圆,求b被覆盖的圆心角区间。

我们首先发现图中所有的线段长度都能求出来。

我们设∠EBA为alpha,显然△ADB和△ACB全等,则设∠DBA=∠CBA=beta

那么

alpha=arctan(AE/EB)

beta=arccos((BD*BD+BA*BA-DA*DA)/(2*BD*BA))=arccos((rb*rb+dis*dis-ra*ra)/(2*rb*dis))

//余弦定理

那么∠DBE=alpha-beta,∠EBC=alpha+beta

(这里可以发现我们圆心角的0度被我们定义在了左边,和常识不同请注意)

我们将圆心角控制在[-180度,180度],所以一旦超过了这个区间我们就要对其进行修改。

修改操作详见gai函数。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
typedef double dl;
const int N=;
const dl poi=acos(-1.0);
struct circle{
dl r;
dl x;
dl y;
}p[N];
struct line{
dl l;
dl r;
}seg[N][*N];
int n,cnt[N];
bool die[N];
inline dl dis(circle a,circle b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline int inc(circle a,circle b){
dl d=dis(a,b);
if(a.r+b.r<d)return ;//两圆相离
if(a.r>b.r&&a.r-b.r>d)return -;//a覆盖b
if(b.r>a.r&&b.r-a.r>d)return ;//b覆盖a
return ;//两圆相交
}
inline void getinc(circle a,circle b,dl &i,dl &j){//a覆盖b
double alpha=atan2((b.y-a.y),(b.x-a.x));
dl d=dis(a,b);
double beta=acos((b.r*b.r+d*d-a.r*a.r)/(*b.r*d));
i=alpha-beta;
j=alpha+beta;
return;
}
inline bool gai(line &a){
if(a.r>poi){
a.r-=*poi;
return ;
}
if(a.l<-poi){
a.l+=*poi;
return ;
}
return ;
}
bool cmp(line a,line b){
return a.l<b.l;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%lf%lf%lf",&p[i].r,&p[i].x,&p[i].y);
for(int j=;j<i;j++){
if(die[j])continue;
int k=inc(p[i],p[j]);
if(!k)continue;
if(k==-){
die[j]=;
continue;
}
cnt[j]++;
getinc(p[i],p[j],seg[j][cnt[j]].l,seg[j][cnt[j]].r);
if(gai(seg[j][cnt[j]])){
cnt[j]++;
seg[j][cnt[j]].l=-poi;
seg[j][cnt[j]].r=seg[j][cnt[j]-].r;
seg[j][cnt[j]-].r=poi;
}
}
}
dl ans=;
for(int i=;i<=n;i++){
if(!die[i]){
dl re=*poi,L,R;
if(cnt[i]){
sort(seg[i]+,seg[i]+cnt[i]+,cmp);
L=seg[i][].l;R=seg[i][].r;
for(int j=;j<=cnt[i];j++){
if(seg[i][j].l>R){
re-=R-L;
L=seg[i][j].l;
R=seg[i][j].r;
}else{
R=max(R,seg[i][j].r);
}
}
re-=R-L;
}
ans+=re*p[i].r;
}
}
printf("%.3lf\n",ans);
return ;
}

BZOJ1043:[HAOI2008]下落的圆盘——题解(配图片)的更多相关文章

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

    1043: [HAOI2008]下落的圆盘 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1598  Solved: 676[Submit][Stat ...

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

    n^2枚举圆盘,用两圆圆心的向量的极角+余弦定理求某个圆覆盖了该圆的哪一段区间(用弧度表示),最后求个区间并. 注意--精度--最好再累计区间的时候,把每个区间的长度减去EPS,防止最后覆盖的总区间超 ...

  3. bzoj1043 [HAOI2008]下落的圆盘

    Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. Input 第一行为1个整数n,N<=1000 ...

  4. BZOJ-1043 [HAOI2008]下落的圆盘

    几何题... 先把所有圆储存起来,然后对于每个圆我们求得之后放下的圆挡住了的部分,求个并集,并把没被挡到的周长加进答案. #include <cstdlib> #include <c ...

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

    [BZOJ1043][HAOI2008]下落的圆盘 Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  ...

  6. 【bzoj1043】下落的圆盘

    [bzoj1043]下落的圆盘 题意 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. \(1\leq n\leq 1000\ ...

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

    下落的圆盘 Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description 有n个圆盘从天而降,后面落下的可 ...

  8. luogu P2510 [HAOI2008]下落的圆盘

    LINK:下落的圆盘 计算几何.n个圆在平面上编号大的圆将编号小的圆覆盖求最后所有没有被覆盖的圆的边缘的总长度. 在做这道题之前有几个前置知识. 极坐标系:在平面内 由极点 极轴 和 极径组成的坐标系 ...

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

    题目描述 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. 输入 第一行为1个整数n,N<=1000接下来n行每行3个实 ...

随机推荐

  1. 获取附加在方法上的Attribute

    如下: class Program { static void Main(string[] args) { var methodInfo = typeof(Program).GetMethod(&qu ...

  2. 怎样下载Firefox与Chrome浏览器驱动

    在浏览器地址栏输入https://www.seleniumhq.org/ 打开Selenium官网 下载Firefox浏览器驱动 解压到本地 下载Chrome浏览器驱动 解压到本地 把这2个驱动放到P ...

  3. 第六模块:WEB框架开发 第1章·Django框架开发50~87

    51-表关系之一对多 52-表关系之多对多 53-表关系之一对一 54-数据库表关系之关联字段与外键约束 55-数据库表关系之sql创建关联表 56-ORM生成关联表模型 57-多表操作之一对多添加记 ...

  4. JS里点击事件判断是否 触发了节点 和给标签添加class属性

    $("#activityType").click(function(e){ if(e.target==$("#bb")[0]){ var bb=document ...

  5. 简单的图片滑动效果插件 jQuery.iocnSlider.js

    近几日在制作一个客户引导页面,其中有一个图片展示而且带滑动的效果.好久没练手了,索性自己写一个插件吧. 依据设计原型,需要满足两套分辨率下图片不同的尺寸,所以在css中使用了media query的相 ...

  6. Java进阶知识点: 枚举值

    Java进阶知识点1:白捡的扩展性 - 枚举值也是对象   一.背景 枚举经常被大家用来储存一组有限个数的候选常量.比如下面定义了一组常见数据库类型: public enum DatabaseType ...

  7. lock+Condition

    关键字 synchronized+wait/notify/notifyAll可以实现等待/通知模式,类ReentrantLock可以实现同样的功能,但需要借助Condition对象.Condition ...

  8. 初涉 Deep Drive Dataset

    Berkeley 大学最近推出的针对自动驾驶的街景数据集,号称比 Cityscapes 数据量更大,可泛化性更好. 语义实例分割(Semantic Instance Segmentation) 数据集 ...

  9. PHP正则相关

    描述字符串排列模式的一种自定义语法规则 如果可以使用字符串函数处理的任务 就不要使用正则 正则表达式 就是通过构建具有特定规则的模式,与输入的字符信息比较 在进行 分割 匹配 查找 替换 等工作   ...

  10. 适合初学者的嵌入式Linux计划

    俗话说万事开头难,刚开始的时候,你是否根本就不知如何开始,上网查资料被一堆堆新名词搞的找不到北,去图书馆看书也是找不到方向?又是arm,又是linux,又是uboot头都大了,不知道自己究竟从哪里开始 ...