zoukankan      html  css  js  c++  java
  • bzoj1043 下落的圆盘

    1043: [HAOI2008]下落的圆盘

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1587  Solved: 669
    [Submit][Status][Discuss]

    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
    分析:一开始的思路是每增加一个圆盘,看它能覆盖到被计入答案的区域,答案减掉这个长度.这个想法似乎是可行的,但是维护每个圆盘哪些位置被覆盖了非常困难.
              换个思路,考虑每个圆盘对答案的贡献:原周长-被后来的圆盘覆盖的周长.实际上后面一部分就是要求周长并,可以将圆拆成一条线段,规定一个起点和终点.但是这样的话还要求两个圆的交点,不好处理.一个比较好的方法是记录被覆盖部分的圆心角,放到[0,2π)这个区间里.利用两个圆心的极角和圆心角可以比较容易地计算.圆心角可以通过余弦定理得到.需要注意的是左右端点<0和≥2π的情况.
    还要判断两圆是否是包含/相离关系.
              最后怎么求周长并?先把弧度并给求出来,乘上半径就是了.具体方法是在左端点+1,右端点-1,用cnt统计+1,-1的和,如果cnt > 0,则ans -= 第i个弧度-第i-1个弧度.ans初始化为2π.(有点复杂,结合代码更好理解)
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const double pi = acos(-1.0),eps = 1e-8;
    
    int n,tot;
    double ans,sum;
    
    struct node
    {
        double r,x,y;
    } e[1010];
    
    struct node2
    {
        double x;
        int id;
    } p[10010];
    
    double D(node a,node b)
    {
        return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    
    bool cmp(node2 a,node2 b)
    {
        return a.x < b.x;
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
            scanf("%lf%lf%lf",&e[i].r,&e[i].x,&e[i].y);
        for (int i = 1; i <= n; i++)
        {
            bool flag = false;
            tot = 0;
            sum = 0.0;
            for (int j = i + 1; j <= n; j++)
            {
                double dist = D(e[i],e[j]);
                if (dist <= e[j].r - e[i].r)  //完全包含了
                {
                    flag = 1;
                    break;
                }
                if (dist > fabs(e[i].r - e[j].r) && dist <= e[i].r + e[j].r)  //必须要相交不能分离
                {
                    double temp = acos((e[i].r * e[i].r + dist * dist - e[j].r * e[j].r) / (2 * e[i].r * dist));
                    double temp2 = atan2(e[j].y - e[i].y,e[j].x - e[i].x);
                    double l = temp2 - temp,r = temp2 + temp;
                    if (l < 0 && r < 0)
                    {
                        l += 2 * pi;
                        r += 2 * pi;
                    }
                    if (l >= 0 && r <= 2 * pi)
                    {
                        p[++tot].x = l;
                        p[tot].id = 1;
                        p[++tot].x = r;
                        p[tot].id = -1;
                    }
                    else if (l < 0)
                    {
                        p[++tot].x = l + 2 * pi;
                        p[tot].id = 1;
                        p[++tot].x = 2 * pi;
                        p[tot].id = -1;
                        p[++tot].x = 0;
                        p[tot].id = 1;
                        p[++tot].x = r;
                        p[tot].id = -1;
                    }
                    else
                    {
                        p[++tot].x = l;
                        p[tot].id = 1;
                        p[++tot].x = 2 * pi;
                        p[tot].id = -1;
                        p[++tot].x = 0;
                        p[tot].id = 1;
                        p[++tot].x = r - 2 * pi;
                        p[tot].id = -1;
                    }
                }
            }
            if (flag)
                continue;
            ans += e[i].r * 2 * pi;
            if (!tot)
                continue;
            sort(p + 1,p + 1 + tot,cmp);
            for(int j = 1; j <= tot; j++)
            {
                if (sum && fabs(p[j].x - p[j-1].x) > eps)
                    ans -= e[i].r * (p[j].x - p[j - 1].x);
                sum += p[j].id;
            }
        }
        printf("%.3lf
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    Python 动图、动画制作 —— moviepy、matplotlib.animation
    理解 t-SNE (Python)
    理解 t-SNE (Python)
    numpy 辨异(二) —— np.identity()/np.eye()
    numpy 辨异(二) —— np.identity()/np.eye()
    走遍中国 —— 大西南
    走遍中国 —— 大西南
    学习 NLP(一)—— TF-IDF
    我对互联网营销时代的发展认知
    [置顶] MyEclipse下安装插件方法(properties文件编辑器Propedit为例)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8119957.html
Copyright © 2011-2022 走看看