首页 > 技术文章 > UVaLive2572 poj1418 UVa1308 Viva Confetti

showson 2016-01-19 21:52 原文

一次放下n个圆

问最终可见的圆的数量

应该是比较经典的问题吧

考虑一个圆与其他每个圆的交点O(n)个

将其割成了O(n)条弧

那么看每条弧的中点 分别向内向外调动eps这个点 则最上面的覆盖这个点的圆可见O(n)

总时间复杂度O(n ** 3)

 

怕炸精度,代码基本抄的rjl的

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<cmath>
  7 #include<vector>
  8 
  9 using namespace std;
 10 
 11 typedef double data_type;
 12 
 13 const data_type eps = 5 * 1e-13;
 14 int dcmp(const data_type& x) {
 15     if(fabs(x) < 0) return 0; return x < 0 ? -1 : 1;
 16 }
 17 
 18 const data_type pi = acos(-1.0), dpi = 2 * acos(-1.0);
 19 
 20 double NormalizeAngle(double rad) {
 21     return rad - dpi * floor(rad / dpi);
 22 }
 23 
 24 typedef const struct Point& Point_cr;
 25 typedef struct Point {
 26     data_type x, y;
 27     Point() {}
 28     Point(data_type x, data_type y) : x(x), y(y) {}
 29     Point operator + (Point_cr rhs) const {
 30         return Point(x + rhs.x, y + rhs.y);
 31     }
 32     Point operator - (Point_cr rhs) const {
 33         return Point(x - rhs.x, y - rhs.y);
 34     }
 35     Point operator * (data_type k) const {
 36         return Point(x * k, y * k);
 37     }
 38     Point operator / (double k) const {
 39         return Point(x / k, y / k);
 40     }
 41     double length() const {
 42         return hypot(x, y);
 43     }
 44     double angle() const {
 45         return atan2(y, x);
 46     }
 47 }Vector;
 48 
 49 double Dot(const Vector& v1, const Vector& v2) {
 50     return v1.x * v2.x + v1.y * v2.y;
 51 }
 52 
 53 double length(const Vector& v) {
 54     return sqrt(Dot(v, v));
 55 }
 56 
 57 typedef const Vector& Vector_cr;
 58 void CircleCircleIntersection(Point_cr c1, double r1, Point c2, double r2, vector<double> &rad) {
 59     double d = (c1 - c2).length();
 60     if(dcmp(d) == 0) return;
 61     if(dcmp(r1 + r2 - d) < 0) return;
 62     if(dcmp(fabs(r1 - r2) - d) > 0) return;
 63     double a = (c2 - c1).angle();
 64     double da = acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
 65     rad.push_back(NormalizeAngle(a + da));
 66     rad.push_back(NormalizeAngle(a - da));
 67 }
 68 
 69 const int N = 100 + 10;
 70 int n;
 71 Point centre[N];
 72 double radius[N];
 73 bool vis[N];
 74 
 75 int topmost(Point p) {
 76     for(int i = n - 1; i >= 0; i--) {
 77         if((centre[i] - p).length() < radius[i]) return i;
 78     }
 79     return -1;
 80 }
 81 
 82 int main() {
 83 #ifdef DEBUG
 84     freopen("in.txt", "r", stdin);
 85     freopen("out.txt", "w", stdout);
 86 #endif
 87     
 88     while(scanf("%d", &n) == 1 && n) {
 89         for(int i = 0; i < n; i++) {
 90             double x, y, r;
 91             scanf("%lf%lf%lf", &x, &y, &r);
 92             centre[i] = Point(x, y);
 93             radius[i] = r;
 94         }
 95         memset(vis, 0, sizeof vis);
 96         for(int i = 0; i < n; i++) {
 97             vector<double> rad;
 98             rad.push_back(0);
 99             rad.push_back(dpi);
100             
101             for(int j = 0; j < n; j++) {
102                 CircleCircleIntersection(centre[i], radius[i], centre[j], radius[j], rad);
103             }
104             
105             sort(rad.begin(), rad.end());
106             
107             for(unsigned j = 0; j < rad.size(); j++) {
108                 double mid = (rad[j] + rad[j+1]) / 2.0;
109                 for(int side = -1; side <= 1; side += 2) {
110                     double r2 = radius[i] - side * eps;
111                     int t = topmost(Point(centre[i].x + cos(mid) * r2, centre[i].y + sin(mid) * r2));
112                     if(t >= 0) vis[t] = 1;
113                 }
114             }
115         }
116         int ans = 0;
117         for(int i = 0; i < n; i++) if(vis[i]) {
118             ans++;
119         }
120         printf("%d\n", ans);
121     }
122     
123     return 0;
124 }
View Code

 

推荐阅读