• poj 1418 Viva Confetti(计算几何,圆)


    题意:每次有n个圆盘,给出每个圆盘的圆心坐标及半径,问最后有几个圆盘可见;

    参考:http://blog.csdn.net/tenlee/article/details/40380599

    思路:大白书上的例题。对于每个圆求与其他圆的交点,看两交点围成的弧的中点是否被覆盖,统计未被覆盖的点数(部分思路);

    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    const int  MAX_N = 128;
    const double EPS = 5e-13;
    const double PI = acos(-1.0);
    
    typedef struct
    {
        double x, y;
    } point;
    
    //两点距离
    double Distance(const point & p1, const point & p2);
    
    //如果一个角大于360,减去360,小于0加上360
    double MainAngle(double a);
    
    int  n;    //number of circles
    point o[MAX_N];  //圆心
    double r[MAX_N];  //圆的弧度
    
    int  pan;   //与这个圆的交点数目
    double pa[2 * MAX_N]; //存放与这个圆所有交点对应的弧度
    int  visible[MAX_N]; //是否被访问过
    int  ans;   //answer
    
    int main()
    {
    
        int i, j, k, t;
        point tp;
        double a, b, d;
        while (scanf("%d", &n), n)
        {
            for (i = 0; i < n; ++i)
            {
                scanf("%lf %lf %lf", &o[i].x, &o[i].y, &r[i]);
                visible[i] = 0;
            }
    
            for (i = 0; i < n; ++i)
            {
                pan = 0;
                pa[pan++] = 0;
                pa[pan++] = 2 * PI;
    
                for (j = 0; j < n; ++j)
                {
                    if (j == i)
                    {
                        continue;
                    }
    
                    d = Distance(o[i], o[j]); //判断两个圆心距离
    
                    if (r[i] + r[j] < d || r[i] + d < r[j] || r[j] + d < r[i]) //包含或不相交的
                    {
                        continue;
                    }
    
                    a = atan2(o[j].y - o[i].y, o[j].x - o[i].x);//atan2(),是求这个点和x轴正方形夹角,*PI/180  得到度数
                    b = acos((r[i] * r[i] + d * d - r[j] * r[j]) / (2 * r[i] * d));
    
                    pa[pan] = MainAngle(a + b);
                    pan++;
                    pa[pan] = MainAngle(a - b);
                    pan++;
                }
    
                sort(pa, pa + pan);
    
                for (j = 0; j < pan - 1; ++j)
                {
                    a = (pa[j] + pa[j + 1]) / 2;
    
                    for (t = -1; t < 2; t += 2) //t = -1 或 1
                    {
                        //将每段圆弧中点往内外各移动很小距离
                        tp.x = o[i].x + (r[i] + t * EPS) * cos(a);
                        tp.y = o[i].y + (r[i] + t * EPS) * sin(a);
    
                        for (k = n - 1; k >= 0; --k)
                        {
                            //如果找到第一个cover point i 的 Arc j 的圆,break
                            if (Distance(tp, o[k]) < r[k])
                            {
                                break;
                            }
                        }
                        visible[k] = 1;
                    }
                }
            }
    
            ans = 0;
    
            for (i = 0; i < n; ++i)
                if (visible[i] == 1)
                {
                    ans++;
                }
    
            printf("%d
    ", ans);
        }
    
        return 0;
    }
    
    
    
    double Distance(const point & p1, const point & p2)
    {
        return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
    }
    
    
    
    double MainAngle(double a)
    {
        while (a > 2 * PI)
        {
            a -= 2 * PI;
        }
        while (a < 0)
        {
            a += 2 * PI;
        }
    
        return a;
    }
  • 相关阅读:
    《C++标准程序库》 第6章 STL Container
    《C++语言99个常见编程错误》
    单例模式
    《C++标准程序库》 第7章 Iterator Adapters
    Shell颜色封装(C++)
    《改善C++程序的150个建议》
    OpenCV之图片的创建、保存和复制
    XMLDOM对象方法:对象事件
    三国中最精辟的十句话
    中国十大名茶及鉴别方法
  • 原文地址:https://www.cnblogs.com/dashuzhilin/p/4948605.html
Copyright © 2020-2023  润新知