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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于BZOJ1043:[HAOI2008]下落的圆盘——题解的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1043: [HAOI2008]下落的圆盘

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

bzoj1043 [HAOI2008]下落的圆盘

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

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

BZOJ 1043HNOI 2008下落的圆盘 判断圆相交+线段覆盖

(c)2006-2024 SYSTEM All Rights Reserved IT常识