一次放下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 }