【BZOJ1043】【HAOI2008】下落的圆盘 计算几何

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/46564199");
}

题解:

给每个圆求一下:

1. 它是不是被之后的某圆整体覆盖。

2. 它的圆周上有哪些弧段被覆盖了。

然后对于每个圆求一下还剩多少周长即可。

上述的“2.”可以用圆的圆心角区间来表示哪些弧段被覆盖。

然后圆心角大小可以用余弦定理求,位置可以取两圆心连线的角度加减其圆心角的一半。

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
#define eps 1e-7
using namespace std;
const double pi=acos(-1.0);

struct Point
{
    double x,y;
    void read(){scanf("%lf%lf",&x,&y);}
    double operator - (const Point &A)const
    {return sqrt((x-A.x)*(x-A.x)+(y-A.y)*(y-A.y));}
};
struct Circle
{
    Point c;
    double r;
    void read()
    {
        scanf("%lf",&r);
        c.read();
    }
}c[N]; // circles
int cnt[N],n;
struct Segment
{
    double l,r;
    Segment(double _l=0,double _r=0):l(_l),r(_r){}
    bool keep()
    {
        if(r>pi)
        {
            r-=2*pi;
            return 1;
        }
        if(l<-pi)
        {
            l+=2*pi;
            return 1;
        }
        return 0;
    }
    bool operator < (const Segment &A)const
    {return l<A.l;}
}seg[N][N<<1],sg;
int inc(const Circle &A,const Circle &B) // 判断半径和圆心距离
{
    double dis=A.c-B.c;
    if(A.r+B.r<dis)return 0;
    if(A.r+eps>B.r&&A.r-B.r+eps>dis)return -1;
    if(B.r+eps>A.r&&B.r-A.r+eps>dis)return 0;
    return 1;
}
void getinc(const Circle &A,const Circle &B,double &ret1,double &ret2)
{
    double angle=atan2(B.c.y-A.c.y,B.c.x-A.c.x),dis=A.c-B.c;
    double dang=acos((B.r*B.r+dis*dis-A.r*A.r)/(2*dis*B.r));
    ret1=angle-dang,ret2=angle+dang;
}
bool die[N];
double ans;
int main()
{
//  freopen("test.in","r",stdin);

    int i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        c[i].read();
        for(j=1;j<i;j++)if(!die[j])if(k=inc(c[i],c[j]))
        {
            if(k==-1)
            {
                die[j]=true;
                continue;
            }
            cnt[j]++;
            getinc(c[i],c[j],seg[j][cnt[j]].l,seg[j][cnt[j]].r);
            if(seg[j][cnt[j]].keep())
            {
                cnt[j]++;
                seg[j][cnt[j]]=Segment(-pi,seg[j][cnt[j]-1].r);
                seg[j][cnt[j]-1].r=pi;
            }
        }
    }
    double remain;
    for(i=1;i<=n;i++)if(!die[i])
    {
        sort(seg[i]+1,seg[i]+cnt[i]+1);
        remain=2*pi,sg.l=sg.r=-remain;
        for(j=1;j<=cnt[i];j++)
        {
            if(seg[i][j].l>sg.r)
            {
                remain-=(sg.r-sg.l);
                sg=seg[i][j];
            }
            else sg.r=max(sg.r,seg[i][j].r);
        }
        remain-=(sg.r-sg.l);
    //  ans+=2*pi*c[i].r*remain/(2*pi);
        ans+=c[i].r*remain;
    }
    printf("%.3lf\n",ans);
    return 0;
}
时间: 2024-12-17 17:43:34

【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]下落的圆盘 计算几何

题目描述 有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π]的部分要切割成还有一个区间 处理起来事实上不是非常麻

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 ****************************

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

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

【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]下落的圆盘——题解

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 Out

【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 *******************************