传送门

首先考虑两个圆覆盖的情况,我们可以求出圆心与交点连线 $A$ 的极角

具体就是求出两圆心连线 $B$ 极角加上余弦定理加反余弦求出 $A,B$ 之间夹角 ,然后覆盖了多少就可以得出

但是多个圆覆盖会重复算,所以离线枚举后面的圆,然后把覆盖的区间按极角排序做一遍类似线段覆盖的操作就行了

区间覆盖的时候注意极角可以会算出负数和大于 $2\pi$ 的情况

思路倒挺简单,计算几何实现起来反正就是一堆细节

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double db;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const db pi=acos(-1.0),pi2=pi*,eps=1e-;
const int N=;
int n;
inline int dcmp(db x) { if(fabs(x)<eps) return ; return x< ? - : ; }
struct Poi {
db x,y;
Poi (db a=,db b=) { x=a,y=b; }
inline Poi operator - (const Poi &tmp) const {
return Poi(x-tmp.x,y-tmp.y);
}
};
inline db Len(Poi A) { return sqrt(A.x*A.x+A.y*A.y); }
inline db angle(Poi A) { return atan2(A.y,A.x); }
struct Circ {
Poi O; db r;
Circ (Poi a=Poi(,),db b=) { O=a,r=b; }
}C[N];
struct dat {
db ang; int type;
dat (db a=,int b=) { ang=a,type=b; }
inline bool operator < (const dat &tmp) const {
return ang<tmp.ang;
}
}D[N];
db work(int p)
{
db res=; int tot=,cnt=;
for(int i=p+;i<=n;i++)
{
db dis=Len(C[i].O-C[p].O);
if( C[p].r+dis<=C[i].r ) return ;//p被完全覆盖
if( dis>=C[p].r+C[i].r || C[i].r+dis<=C[p].r ) continue;//p没被覆盖,记得可能 i 在 p 里面
db alp=acos( (dis*dis+C[p].r*C[p].r-C[i].r*C[i].r)/(*dis*C[p].r) ),k=angle(C[i].O-C[p].O);
db l=k-alp,r=k+alp;//两个交点的极角
if(dcmp(l)<&&dcmp(r)<) { D[++tot]=dat(l+pi2,); D[++tot]=dat(r+pi2,-); continue; }
if(dcmp(l)>=&&r<=pi2) { D[++tot]=dat(l,); D[++tot]=dat(r,-); continue; }
if(dcmp(l)<&&dcmp(r)>=)
{
D[++tot]=dat(l+pi2,); D[++tot]=dat(pi2,-);
D[++tot]=dat(,); D[++tot]=dat(r,-);
}
if(dcmp(l)>=&&r>pi2)
{
D[++tot]=dat(,); D[++tot]=dat(r-pi2,-);
D[++tot]=dat(l,); D[++tot]=dat(pi2,-);
}
}
sort(D+,D+tot+);
for(int i=;i<=tot;i++)
{
if(D[i].type==&&!cnt) res+=D[i].ang-D[i-].ang;//线段覆盖
cnt+=D[i].type;
}
res+=pi2-D[tot].ang;
return C[p].r*res;
}
int main()
{
n=read(); db a,b,c,ans=;
for(int i=;i<=n;i++)
{
scanf("%lf%lf%lf",&a,&b,&c);
C[i]=Circ( Poi(b,c) , a );
}
for(int i=;i<=n;i++) ans+=work(i);
printf("%.3f\n",ans);
return ;
}

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

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

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

  2. 洛谷P2510 [HAOI2008]下落的圆盘(计算几何)

    题面 传送门 题解 对于每个圆,我们单独计算它被覆盖的周长是多少 只有相交的情况需要考虑,我们需要知道相交的那段圆弧的角度,发现其中一个交点和两个圆的圆心可以构成一个三角形且三边都已经知道了,那么我们 ...

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

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

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

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

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

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

  6. [HAOI2008]下落的圆盘

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

  7. bzoj1043 [HAOI2008]下落的圆盘

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

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

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

  9. Bzoj1313 [HAOI2008]下落的圆盘

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

随机推荐

  1. C# for循环测试

  2. UVa 1596 Bug Hunt (string::find && map && 模拟)

    题意 : 给出几组由数组定义与赋值构成的编程语句, 有可能有两种BUG, 第一种为数组下标越界, 第二种为使用尚未定义的数组元素, 叫你找出最早出现BUG的一行并输出, 每组以' . '号分隔, 当有 ...

  3. JUnit——Failure与Error

    (1)Failure是指测试失败(2)Error是指测试程序本身出错

  4. SPOJ 913 Query on a tree II

    spoj题面 Time limit 433 ms //spoj的时限都那么奇怪 Memory limit 1572864 kB //1.5个G,疯了 Code length Limit 15000 B ...

  5. 将DVD.iso 挂载到虚拟机

    将DVD.iso挂载到虚机之后,默认设备名是/dev/sr0 挂载DVD.iso文件到/mnt. 操作: mount /dev/sr0 /mnt 查看: ll /mnt

  6. 第一次试验报告&学习总结

    打印输出所有的"水仙花数",所谓"水仙花数"是指一个3位数,其中各位数字立方和等于该数本身.例如,153是一个"水仙花数". 试验代码: p ...

  7. VC CString,int,string,char*之间的转换

    CString转string : CString strMfc = "test"; std::string strStr; strStr = strMfc.GetBuffer(); ...

  8. leetcode 374. 猜数字大小(python)

    我们正在玩一个猜数字游戏. 游戏规则如下:我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字.每次你猜错了,我会告诉你这个数字是大了还是小了.你调用一个预先定义好的接口 guess(int n ...

  9. The file is inaccessible to Server.

    ArcGIS Unable to Start serviceserver安装后,启动服务失败,报错信息如下:Unable to Start service. Error (Server object  ...

  10. 阶段3 1.Mybatis_03.自定义Mybatis框架_2.自定义Mybatis的分析-创建代理对象的分析

    如何创建代理对象,以及使用设计模式带来的优势 调用的组合关系 不关注的,执行JDBC那一套.第二个是解析XML,解析的技术有很多.