zoukankan      html  css  js  c++  java
  • uva 1308

    这个题目的方法是将圆盘分成一个个圆环,然后判断这些圆环是否被上面的圆覆盖;

    如果这个圆的圆周上的圆弧都被上面的覆盖,暂时把它标记为不可见;

    然后如果他的头上有个圆,他有个圆弧可见,那么他自己本身可见,并且可以把这条圆弧下面的第一个圆重新标记为可见;

    另外,圆弧可见还是不可见利用它的中点来进行判断;

      1 #include <cstdio>
      2 #include <cmath>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 
      7 using namespace std;
      8 
      9 const int maxn = 100 + 10;
     10 const double eps = 1e-14;        //别开太大,样例数据就到达1e-11级别
     11 const double pi = acos(-1);
     12 
     13 int dcmp(double x)
     14 {
     15     return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
     16 }
     17 
     18 struct Point
     19 {
     20     double x;
     21     double y;
     22 
     23     Point(double x = 0, double y = 0):x(x), y(y) {}
     24 
     25     bool operator < (const Point& e) const
     26     {
     27         return dcmp(x - e.x) < 0 || (dcmp(x - e.x) == 0 && dcmp(y - e.y) < 0);
     28     }
     29 
     30     bool operator == (const Point& e) const
     31     {
     32         return dcmp(x - e.x) == 0 && dcmp(y - e.y) == 0;
     33     }
     34 
     35     int read()
     36     {
     37         return scanf("%lf%lf", &x, &y);
     38     }
     39 };
     40 
     41 typedef Point Vector;
     42 
     43 Vector operator + (Point A, Point B)
     44 {
     45     return Vector(A.x + B.x, A.y + B.y);
     46 }
     47 
     48 Vector operator - (Point A, Point B)
     49 {
     50     return Vector(A.x - B.x, A.y - B.y);
     51 }
     52 
     53 Vector operator * (Point A, double p)
     54 {
     55     return Vector(A.x * p, A.y * p);
     56 }
     57 
     58 Vector operator / (Point A, double p)
     59 {
     60     return Vector(A.x / p, A.y / p);
     61 }
     62 
     63 struct Circle
     64 {
     65     Point c;
     66     double r;
     67 
     68     Circle() {}
     69     Circle(Point c, double r):c(c), r(r) {}
     70 
     71     int read()
     72     {
     73         return scanf("%lf%lf%lf", &c.x, &c.y, &r);
     74     }
     75 
     76     Point point(double a)
     77     {
     78         return Point(c.x + r * cos(a), c.y + r * sin(a));
     79     }
     80 };
     81 
     82 double Dot(Vector A, Vector B)
     83 {
     84     return A.x * B.x + A.y * B.y;
     85 }
     86 
     87 double Length(Vector A)
     88 {
     89     return sqrt(Dot(A, A));
     90 }
     91 
     92 double angle(Vector v)      //求向量的极角
     93 {
     94     return atan2(v.y, v.x);
     95 }
     96 
     97 bool PointInCircle(Point p, Circle C)       //判断点是否在圆内
     98 {
     99     double dist = Length(p - C.c);
    100     if(dcmp(dist - C.r) > 0) return 0;      //这里我选择点在圆边上不算在圆内
    101     else return 1;
    102 }
    103 
    104 bool CircleInCircle(Circle A, Circle B)         //判断圆在圆内
    105 {
    106     double cdist = Length(A.c - B.c);
    107     double rdiff = B.r - A.r;
    108     if(dcmp(A.r - B.r) <= 0 && dcmp(cdist - rdiff) <= 0) return 1;      //包括重合,内切和内含的情况
    109     return 0;
    110 }
    111 
    112 int n;
    113 Circle C[maxn];
    114 bool vis[maxn];
    115 vector<double> pointAng[maxn];
    116 
    117 int GetCircleCircleIntersection(int c1, int c2)       //求圆与圆的交点
    118 {
    119     Circle C1 = C[c1];
    120     Circle C2 = C[c2];
    121     double d = Length(C1.c - C2.c);
    122     if(dcmp(d) == 0)
    123     {
    124         if(dcmp(C1.r - C2.r) == 0) return -1;       //两圆重合
    125         return 0;       //同心圆但不重合
    126     }
    127     if(dcmp(C1.r + C2.r - d) < 0) return 0;     //外离
    128     if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;       //内含
    129     double a = angle(C2.c - C1.c);
    130     double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));
    131     Point p1 = C1.point(a + da);
    132     Point p2 = C1.point(a - da);
    133     if(p1 == p2) return 1;      //相切
    134     pointAng[c1].push_back(a + da);     //相切的点不处理,只要相交的
    135     pointAng[c1].push_back(a - da);
    136     return 2;
    137 }
    138 
    139 void init()
    140 {
    141     for(int i = 0; i < n; i++) pointAng[i].clear();
    142     memset(vis, 0, sizeof(vis));
    143 }
    144 
    145 void read()
    146 {
    147     for(int i = 0; i < n; i++) C[i].read();
    148 }
    149 
    150 void solve()
    151 {
    152     for(int i = 0; i < n; i++)      //圆两两相交,得各圆交点集合
    153         for(int j = 0; j < n; j++) if(i != j)
    154                 GetCircleCircleIntersection(i, j);
    155     for(int i = 0; i < n; i++)
    156     {
    157         sort(pointAng[i].begin(), pointAng[i].end());       //各圆交点按极角排序
    158         vector<double>::iterator iter = unique(pointAng[i].begin(), pointAng[i].end());     //去重,可减少运行时间,不去重也能AC
    159         pointAng[i].resize(distance(pointAng[i].begin(), iter));
    160     }
    161     for(int i = 0; i < n; i++)      //判断第i个圆上的弧
    162     {
    163         int sz = pointAng[i].size();
    164         if(!sz)         //此圆不与其他圆相交
    165         {
    166             bool ok = 1;
    167             for(int k = i+1; k < n; k++) if(CircleInCircle(C[i], C[k]))         //判上面是否有圆把它覆盖掉
    168                 {
    169                     ok = 0;
    170                     break;
    171                 }
    172             if(ok) vis[i] = 1;
    173         }
    174         else
    175         {
    176             pointAng[i].push_back(pointAng[i][0]);
    177             for(int j = 0; j < sz; j++)         //第i个圆上的第j条弧
    178             {
    179                 bool ok = 1;
    180                 Point pm = C[i].point((pointAng[i][j] + pointAng[i][j+1]) / 2);     //取弧的中点
    181                 for(int k = i+1; k < n; k++) if(PointInCircle(pm, C[k]))
    182                     {
    183                         ok = 0;
    184                         break;
    185                     }
    186                 if(ok)
    187                 {
    188                     vis[i] = 1;
    189                     for(int u = i-1; u >= 0; u--)if(PointInCircle(pm, C[u]))        //把这段圆弧下的圆设为可见
    190                         {
    191                             vis[u] = 1;
    192                             break;
    193                         }
    194                 }
    195             }
    196         }
    197     }
    198     int ret = 0;
    199     for(int i = 0; i < n; i++) if(vis[i]) ret++;
    200     printf("%d
    ", ret);
    201 }
    202 
    203 int main()
    204 {
    205     while(scanf("%d", &n) == 1 && n)
    206     {
    207         init();
    208         read();
    209         solve();
    210     }
    211     return 0;
    212 }
    View Code
  • 相关阅读:
    Fedora 19+ 启动顺序调整
    朗科U903 低级格式化后,量产错误:read onlypage (控制器芯片群联2251-03)的解决方案
    python中快速删除实例对象中的所有属性
    python中如何用sys.excepthook来对全局异常进行捕获、显示及输出到error日志中
    通过ctypes获得python windows process的内存使用情况
    Python的XMLRPC机制:实现跨进程间、client/server端通信
    PIL Image 转成 wx.Image、wx.Bitmap
    wxpython线程安全的方法
    11
    列表去重的几种方法
  • 原文地址:https://www.cnblogs.com/yours1103/p/3406531.html
Copyright © 2011-2022 走看看