有 n 个圆盘从天而降,后面落下的可以盖住前面的。最后按掉下的顺序,在平面上依次测得每个圆盘的圆心和半径,问下落完成后从上往下看,整个图形的周长是多少,即你可以看到的圆盘的轮廓的圆盘的轮廓总长.例如下图的黑色线条的总长度即为所求。

【输入格式】

第一行为1个整数n

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

【输出格式】

仅一个实数,表示所求的总周长,答案保留3位小数.

【样例输入】

2
1 0 0
1 1 0

【样例输出】

10.472

【提示】

30%的数据,n<=10

100%的数据,n<=1000

数学问题 计算几何

用余弦定理和三角函数可以计算出两圆相交部分的弧长。

对于每个圆,计算它和在它之后落下的所有圆的角。记录相交部分的弧对应的圆心角范围。将“圆心角”区间离散到0~2pi的数轴上,做线段覆盖。

知道了未被覆盖的角总共有多大,就能算出该圆未被覆盖的弧有多长。

注意如果求出的覆盖部分圆心角范围超出了0~2pi,要变换到0~2pi范围内

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-;
const int mxn=;
struct point{
double x,y;
point operator + (point b){return (point){x+b.x,y+b.y};}
point operator - (point b){return (point){x-b.x,y-b.y};}
double operator * (point b){return x*b.x+y*b.y;}
};
inline double Cross(point a,point b){
return a.x*b.y-a.y*b.x;
}
inline double dist(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline double Len(point a){return sqrt(a*a);}
struct cir{
double x,y;
double r;
point operator + (cir b){return (point){x+b.x,y+b.y};}
point operator - (cir b){return (point){x-b.x,y-b.y};}
}c[mxn];
inline bool cover(cir a,cir b){
return (a.r>=b.r+Len(a-b));
}
struct line{
double l,r;
bool operator < (line b)const{
return (l<b.l)|| (l==b.l && r<b.r);
}
};
line CX(cir a,cir b){
double dis=Len(b-a);
double angle=acos((a.r*a.r+dis*dis-b.r*b.r)/(*a.r*dis));
double deg=atan2(a.x-b.x,a.y-b.y);//统一旋转pi角度,保证在-2pi~2pi范围内
return (line){deg-angle,deg+angle};
/* double t=(a.r*a.r+dis*dis-b.r*b.r)/(2*dis);
double st=atan2(a.x-b.x,a.y-b.y);
double l=acos(t/a.r);
return (line){st-l,st+l};*/
}
vector<line>ve;
int n;
double ans=;
void calc(int x){
for(int i=x+;i<=n;i++){if(cover(c[i],c[x]))return;}//被完全覆盖
ve.clear();
for(int i=x+;i<=n;i++){
if(cover(c[x],c[i]))continue;//完全覆盖
line tmp;
if(c[x].r+c[i].r>Len(c[i]-c[x])) tmp=CX(c[x],c[i]);
else continue;
if(tmp.l<) tmp.l+=*pi;
if(tmp.r<) tmp.r+=*pi;
if(tmp.l>tmp.r){//拆分
ve.push_back((line){,tmp.r});
ve.push_back((line){tmp.l,*pi});
}
else ve.push_back(tmp);
}
sort(ve.begin(),ve.end());
// printf("mid\n");
double now=,ran=;
for(int i=;i<ve.size();i++){//线段覆盖
line tmp=ve[i];
// printf("i:%d %.3f %.3f\n",i,tmp.l,tmp.r);
if(tmp.l>now){ran+=tmp.l-now;now=tmp.r;}
else now=max(now,tmp.r);
}
ran+=*pi-now;
ans+=c[x].r*ran;//累加半径
return;
}
int main(){
freopen("disc.in","r",stdin);
freopen("disc.out","w",stdout);
int i,j;
scanf("%d",&n);
for(i=;i<=n;i++){
scanf("%lf%lf%lf",&c[i].r,&c[i].x,&c[i].y);
}
for(i=n;i>=;i--){
calc(i);
// printf("ans:%.3f\n",ans);
}
printf("%.3f\n",ans);
return ;
}

Bzoj1313 [HAOI2008]下落的圆盘的更多相关文章

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

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

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

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

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

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

  4. BZOJ 1043 HAOI2008 下落的圆盘 计算几何

    题目大意:n个圆盘依次下落.求终于能看到的轮廓线面积 円盘反对! 让我们一起团结起来! 赶走円盘! 咳咳.非常神的一道题 今天去看了题解和白书才搞出来-- 首先我们倒着做 对于每一个圆盘处理出在它之后 ...

  5. [HAOI2008]下落的圆盘

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

  6. bzoj1043 [HAOI2008]下落的圆盘

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

  7. BZOJ1043:[HAOI2008]下落的圆盘——题解(配图片)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1043 Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周 ...

  8. 1043: [HAOI2008]下落的圆盘

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1725  Solved: 743[Submit][Status][Discuss] Descripti ...

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

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

随机推荐

  1. C++各种类型的简单排序大汇总~

    啊,排序的技能点也太多了吧!!!LITTLESUN快要**在排序的技能场了啊!(划掉)经历了两天48小时2880分钟172800秒的艰苦奋斗,终于终于终于学的差不多了!明天就可以去打排序的小怪喽!(撒 ...

  2. 用gradle编译任意结构的Android项目

    ## 需求 * 继续用`Eclipse`项目的结构,但是使用`gradle`编译,或者说任意的项目结构进行编译. ## 解决方案 1. Android studio的项目结构 1. Android S ...

  3. Qt Charts_Audio实践

    这里完全是照搬帮助文档中的代码生成的程序 上预览图 工程文件代码 #------------------------------------------------- # # Project crea ...

  4. Python|花了一天,为大家整理的一套来自外国大佬的密码速查表

    简单的HTTPS服务器 检查证书信息 输出 生成自签名证书 输出 准备一个签名注册请求 输出 生成无密码的RSA秘钥文件 用一个私钥给文件签名 输出 从签名验证一个文件 输出 通过pem文件做RSA加 ...

  5. 【转】ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    原文链接:https://www.cnblogs.com/yilezhu/p/9241261.html 引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必 ...

  6. 企业级Tomcat部署配置

    1.1 Tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun和其他一些公司及个人 ...

  7. 装机、UEFI双系统安装

    装机设置 设置默认中图标显示查看-选项-查看-应用到文件夹 控制面板-语言-管理输入法 word-选项-取消输入法设置处于活动状态word-字体-设置默认值 高DPI的显示屏,需要使用125%的缩放, ...

  8. 【iOS开发】字典的快速赋值 setValuesForKeysWithDictionary

    前言 在学习解析数据的时候,我们经常是这么写的:PersonModel.h文件中 @property (nonatomic,copy)NSString *name; @property (nonato ...

  9. vue2.0中动画

    #vue2.0中css动画不显示的坑: transition中包含的两个标签如果相同(此处都是p标签),需要为元素指定key.如果标签名不同的话,不指定key也可以出现动画效果. #vue2.0中js ...

  10. 开发一个delphi写的桌面图标管理代码

    参加工作了就很少有时间去玩delphi了,这个适合初学者看看,大神勿喷 工具 delhpi7.0 access数据库 原则win下有安装office就可用 当初不太熟悉sqlite所有没用这做数据库. ...