BZOJ1043:[HAOI2008]下落的圆盘——题解

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

我们可以用弧度制来表示当前圆被覆盖的部分。

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

(图片被割了,所以等有时间再补……)

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
typedef double dl;
const int N=1001;
const dl poi=acos(-1.0);
struct circle{
    dl r;
    dl x;
    dl y;
}p[N];
struct line{
    dl l;
    dl r;
}seg[N][2*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 0;//两圆相离
    if(a.r>b.r&&a.r-b.r>d)return -1;//a覆盖b
    if(b.r>a.r&&b.r-a.r>d)return 0;//b覆盖a
    return 1;//两圆相交
}
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)/(2*b.r*d));
    i=alpha-beta;
    j=alpha+beta;
    return;
}
inline bool gai(line &a){
    if(a.r>poi){
    a.r-=2*poi;
    return 1;
    }
    if(a.l<-poi){
    a.l+=2*poi;
    return 1;
    }
    return 0;
}
bool cmp(line a,line b){
    return a.l<b.l;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
    scanf("%lf%lf%lf",&p[i].r,&p[i].x,&p[i].y);
    for(int j=1;j<i;j++){
        if(die[j])continue;
        int k=inc(p[i],p[j]);
        if(!k)continue;
        if(k==-1){
        die[j]=1;
        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]-1].r;
        seg[j][cnt[j]-1].r=poi;
        }
    }
    }
    dl ans=0;
    for(int i=1;i<=n;i++){
    if(!die[i]){
        dl re=2*poi,L,R;
        if(cnt[i]){
        sort(seg[i]+1,seg[i]+cnt[i]+1,cmp);
        L=seg[i][1].l;R=seg[i][1].r;
        for(int j=2;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 0;
}
时间: 2024-10-17 02:01:24

BZOJ1043:[HAOI2008]下落的圆盘——题解的相关文章

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

1043: [HAOI2008]下落的圆盘 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1598  Solved: 676[Submit][Status][Discuss] Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  Input 第一行为1个整数n,N<=1000接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标

BZOJ1043 [HAOI2008]下落的圆盘

倒过来做,然后就变成了线段覆盖问题了. 线段覆盖就是贪心即可... 但是好烦好烦= =,需要耐心和几何基础2333 1 /************************************************************** 2 Problem: 1043 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:240 ms 7 Memory:872 kb 8 ****************************

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

[BZOJ1043][HAOI2008]下落的圆盘 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 题解:对于每个圆,我们枚举它后面的

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

题目描述 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. 输入 第一行为1个整数n,N<=1000接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标. 输出 最后的周长,保留三位小数 样例输入 2 1 0 0 1 1 0 样例输出 10.472 题解 计算几何 考虑从下到上的每一个圆,它被其它的圆覆盖了多少.即考虑它被覆盖了多少弧度. 考虑两个圆,如果相离则不覆盖,内含判断一下包含关系. 如果

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

题目大意:n个圆盘依次下落.求终于能看到的轮廓线面积 円盘反对! 让我们一起团结起来! 赶走円盘! 咳咳.非常神的一道题 今天去看了题解和白书才搞出来-- 首先我们倒着做 对于每一个圆盘处理出在它之后落下的圆盘和它的覆盖区间 然后求一个区间并就能算出这个圆盘的可见弧长 然后就是相交部分怎么求的问题了 首先两个圆必须相交 然后作圆心1到圆心2的向量 用atan2求出极角 然后利用余弦定理求出两个交点和圆心连线的夹角就可以 注意区间不在[0,2π]的部分要切割成还有一个区间 处理起来事实上不是非常麻

【BZOJ】1043: [HAOI2008]下落的圆盘(计算几何+贪心)

http://www.lydsy.com/JudgeOnline/problem.php?id=1043 唯一让我不会的就是怎么求圆的周长并QAAQ... 然后发现好神!我们可以将圆弧变成$[0, 2 \pi ]$的直线! 然后一定要注意!起点是$(1, 0)$(单位圆) 首先学了余弦定理... 在三角形ABC中 $$cos A=\frac{|AB|^2+|AC|^2-|BC|^2}{2|AB| |AC|}$$ 证明很简单... $$\begin{align}|{BC}|^2 & = \vec{

BZOJ 1043: [HAOI2008]下落的圆盘

Description 求几个圆交起来的周长..\(n\leqslant 10^3\) Solution 计算几何. 圆圆求交.. Code /************************************************************** Problem: 1043 User: BeiYu Language: C++ Result: Accepted Time:520 ms Memory:1308 kb *******************************

【bzoj_1043】[HAOI2008]下落的圆盘

水题?好像是的.(可惜我不会,默默捂脸= ̄ω ̄= 首先明确一点.两个圆相交,圆上的弧一定是从du-ang到du+ang的,不管是优弧还是劣弧.(du代表两圆心连线的atan2值,ang就是用余弦定理算出来的那个角) 然后就爽了. 把所有圆后面的圆扫一遍,看看有哪些焦点,用角度的形式记录下有哪些弧被覆盖,然后求并. 注意范围必须映射到一个长度为2π的区间内,否则求并的时候会出问题.

JZYZOJ1502 [haoi2008]下落的圆盘 计算几何 贪心

http://172.20.6.3/Problem_Show.asp?id=1502这种题用了快一天才写出来也是真的辣鸡.主要思路就是计算一下被挡住的弧度然后对弧度进行贪心.最开始比较困扰的是求弧度值及其起始位置的部分,弧度值很好求,位置有点恶心,我的起始位置设置的是圆的十二点方向顺时针到起始位置的弧度值,然后我分了四种情况讨论(因为遮挡的方向有两种不同情况,遮挡部分弧度值与180度的关系又是两种情况),应该是有更简单的方法的,但是我只能想出来这种了... 代码 1 #include<cstdi