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. xencenter迁移云主机方法

    问题:POOL中计算节点内存不足. 解决方法:1.为计算节点添加内存(费用高)2.将部分资源迁移到其它POOL中. 方法: 1.选择要迁移的虚拟机 2.选择保存路径 这里可以看到可以批量导出: 注意: ...

  2. Unity Shader学习笔记 - 用UV动画实现沙滩上的泡沫

    这个泡沫效果来自远古时代的Unity官方海岛Demo, 原效果直接复制3个材质球在js脚本中做UV动画偏移,这里尝试在shader中做动画并且一个pass中完成: // Upgrade NOTE: r ...

  3. 代码对齐 (Alignment of Code,ACM/ICPC NEERC 2010,UVa1593)

    题目描述: 解题思路: 输入时提出单个字符串,并用一个数组记录每列最长长度,格式化输出 #include <iostream> #include <algorithm> #in ...

  4. spark集群安装部署

    通过Ambari(HDP)或者Cloudera Management (CDH)等集群管理服务安装和部署在此不多介绍,只需要在界面直接操作和配置即可,本文主要通过原生安装,熟悉安装配置流程. 1.选取 ...

  5. (原创)白话KMP算法详解

    引子:BF暴力算法 KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下: 初学串的模式匹配时,我们都会接触到,或者说应该能想 ...

  6. 您的下个中文网站可以使用的5个高质量中文Webfont

    你有没有考虑为什么中文网站的版式风格不像大多数现代英文网站那样丰富?您想了解如何让您的下一个中文网站项目更吸引用户的眼球么?继续往下读吧…… 根据Smashing Magazine进行的一项调查显示  ...

  7. Python3 Tkinter-Text

    1.创建 from tkinter import * root=Tk() t=Text(root) t.pack() root.mainloop() 2.添加文本 from tkinter impor ...

  8. (转载)IE8+兼容经验小结

    本文分享下我在项目中积累的IE8+兼容性问题的解决方法.根据我的实践经验,如果你在写HTML/CSS时候是按照W3C推荐的方式写的,然后下面的几点都关注过,那么基本上很大一部分IE8+兼容性问题都OK ...

  9. css模仿微信弹出菜单

      css模仿微信弹出菜单 效果图: html: <div class="action-sheet-backdrop"> <div class="act ...

  10. java — 值传递和引用传递

    在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用传递对象这一事实并不意味着 Java 应用程序按引用传递参数.参数可以是对象引用,而 Java ...