LA 2572 (求可见圆盘的数量) Kanazawa

题意:

把n个圆盘依次放到桌面上,按照放置的先后顺序给出这n个圆盘的圆心和半径,输出有多少个圆盘可见(即未被全部覆盖)。

分析:

题中说对输入数据进行微小扰动后答案不变。

所露出的部分都是由若干小圆弧组成的。因此求出每个圆与其他圆相交的小圆弧,取圆弧的终点,分别向里和向外移动一个很小的距离的到P'。标记包含P'的最上面的那个圆为可见。

  1 //#define LOCAL

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <algorithm>

  5 #include <cmath>

  6 #include <vector>

  7 using namespace std;

  8 

  9 const int maxn = 110;

 10 const double PI = acos(-1.0);

 11 const double Two_PI = PI * 2;

 12 const double eps = 5 * 1e-13;

 13 int n;

 14 double radius[maxn];

 15 bool vis[maxn];

 16 

 17 int dcmp(double x)

 18 {

 19     if(fabs(x) < eps)    return 0;

 20     else return x < 0 ? -1 : 1;

 21 }

 22 

 23 struct Point

 24 {

 25     double x, y;

 26     Point(double x=0, double y=0):x(x), y(y) {}    

 27 };

 28 typedef Point Vector;

 29 Point operator + (Point A, Point B)    { return Point(A.x+B.x, A.y+B.y); }

 30 Point operator - (Point A, Point B)    { return Point(A.x-B.x, A.y-B.y); }

 31 Vector operator * (Vector A, double p){ return Vector(A.x*p, A.y*p); }

 32 Vector operator / (Vector A, double p){ return Vector(A.x/p, A.y/p); }

 33 Point center[maxn];

 34 

 35 double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }

 36 double Length(Vector A){ return sqrt(Dot(A, A)); }

 37 double angle(Vector v)    { return atan2(v.y, v.x); }

 38 double NormalizeAngle(double rad)

 39 {//将所求角度化到0到2π之间 

 40     return rad - Two_PI*(floor(rad/Two_PI));

 41 }

 42 

 43 void getCCIntersection(Point c1, double r1, Point c2, double r2, vector<double>& rad)

 44 {

 45     double d = Length(c1 - c2);

 46     if(dcmp(d) == 0)    return;

 47     if(dcmp(d-r1-r2) > 0)    return;

 48     if(dcmp(d-fabs(r1-r2)) < 0)    return;

 49     

 50     double a = angle(c2-c1);

 51     double ag = acos((r1*r1+d*d-r2*r2)/(2*r1*d));

 52     rad.push_back(NormalizeAngle(a + ag));

 53     rad.push_back(NormalizeAngle(a - ag));

 54 }

 55 

 56 int topmost(Point P)

 57 {

 58     for(int i = n-1; i >= 0; --i)

 59         if(Length(P-center[i]) < radius[i])    return i;

 60     return -1;

 61 }

 62 

 63 int main(void)

 64 {

 65     #ifdef LOCAL

 66         freopen("2572in.txt", "r", stdin);

 67     #endif

 68     

 69     while(scanf("%d", &n) == 1 && n)

 70     {

 71         for(int i = 0; i < n; ++i)

 72             scanf("%lf%lf%lf", &center[i].x, &center[i].y, &radius[i]);

 73         memset(vis, 0, sizeof(vis));

 74         

 75         for(int i = 0; i < n; ++i)

 76         {

 77             vector<double> rad;

 78             rad.push_back(0.0);

 79             rad.push_back(Two_PI);

 80             for(int j = 0; j < n && j != i; ++j)

 81                 getCCIntersection(center[i], radius[i], center[j], radius[j], rad);

 82             sort(rad.begin(), rad.end());

 83             

 84             for(int j = 0; j < rad.size() - 1; ++j)

 85             {

 86                 double mid = (rad[j] + rad[j+1]) / 2.0;

 87                 for(int side = -1; side <= 1; side += 2)

 88                 {

 89                     double r = radius[i] + side*eps;

 90                     int t = topmost(Point(center[i].x+r*cos(mid), center[i].y+r*sin(mid)));

 91                     if(t >= 0)    vis[t] = true;

 92                 }

 93             }

 94         }

 95         int ans = 0;

 96         for(int i = 0; i < n; ++i)    if(vis[i])    ++ans;

 97         printf("%d\n", ans);

 98     }

 99 

100     return 0;

101 }
代码君

 

你可能感兴趣的:(wa)