hdu 1077 (圆交)

Problem - 1077

  我们可以知道,当这个单位圆可以覆盖到最多的点的时候,必定最少有两个点位于这个圆的圆周上,于是就有网上众多的O(N^3)的枚举两个在圆上的点的暴搜做法。

  然而这题是可以用圆交来做的。

  我们以一条鱼的位置作为圆心,半径为1的圆的周围随便找一个点都能把这条鱼抓到。这时,我们可以做出很多个这样的圆,半径都为1。

  然后,求一下这些圆的交集,叠起来的最高层数就是最多能获得的鱼的数目。

  这里的圆交不需要实现求面积这部分,于是只需要离散一下交点就行了。

  1y。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <iomanip>
  6 #include <cmath>
  7 
  8 using namespace std;
  9 
 10 const double EPS = 1e-8;
 11 const double PI = acos(-1.0);
 12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
 13 template<class T> T sqr(T x) { return x * x;}
 14 typedef pair<double, double> Point;
 15 #define x first
 16 #define y second
 17 
 18 Point operator + (Point a, Point b) { return Point(a.x + b.x, a.y + b.y);}
 19 Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y);}
 20 Point operator * (Point a, double p) { return Point(a.x * p, a.y * p);}
 21 Point operator * (double p, Point a) { return Point(a.x * p, a.y * p);}
 22 Point operator / (Point a, double p) { return Point(a.x / p, a.y / p);}
 23 
 24 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
 25 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
 26 inline double veclen(Point a) { return sqrt(dot(a, a));}
 27 inline double angle(Point a) { return atan2(a.y, a.x);}
 28 inline Point vecunit(Point a) { return a / veclen(a);}
 29 inline Point normal(Point a) { return Point(-a.y, a.x) / veclen(a);}
 30 
 31 struct Line {
 32     Point s, t;
 33     Line() {}
 34     Line(Point s, Point t) : s(s), t(t) {}
 35     Point vec() { return t - s;}
 36     Point point(double p) { return s + vec() * p;}
 37 } ;
 38 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
 39 
 40 struct Circle {
 41     Point c;
 42     double r;
 43     Circle() {}
 44     Circle(Point c, double r) : c(c), r(r) {}
 45     Point point(double p) { return c + r * Point(cos(p), sin(p));}
 46     bool in(Point p) { return sgn(veclen(p - c) - r) < 0;}
 47 } ;
 48 
 49 const double R = 1000.0;
 50 const int N = 333;
 51 int n;
 52 Circle cir[N];
 53 
 54 void input() {
 55     cin >> n;
 56     for (int i = 0; i < n; i++) {
 57         cin >> cir[i].c.x >> cir[i].c.y;
 58         cir[i].c = cir[i].c * R;
 59         cir[i].r = R;
 60     }
 61 }
 62 
 63 bool ccint(int _a, int _b, double *sol) {
 64     Circle a = cir[_a], b = cir[_b];
 65     double d = veclen(a.c - b.c), dr = fabs(a.r - b.r);
 66     if (sgn(d - a.r - b.r) > 0) return 0;
 67     if (sgn(dr - d) >= 0) {
 68         if (a.r < b.r || sgn(a.r - b.r) == 0 && _a < _b) {
 69             sol[0] = -PI;
 70             sol[1] = PI;
 71             return 1;
 72         }
 73         return 0;
 74     }
 75     double ang = angle(b.c - a.c);
 76     double da = acos(fabs(sqr(a.r) + sqr(d) - sqr(b.r)) / (2 * a.r * d));
 77     sol[0] = ang - da;
 78     sol[1] = ang + da;
 79     return 1;
 80 }
 81 
 82 typedef pair<double, int> Event;
 83 Event ev[N << 1];
 84 bool cmp(Event a, Event b) {
 85     if (sgn(a.x - b.x)) return a.x < b.x;
 86     return a.y > b.y;
 87 }
 88 
 89 int cal(int id) {
 90     int tt = 0;
 91     double _[2];
 92     for (int i = 0; i < n; i++) {
 93         if (i == id) continue;
 94         if (ccint(id, i, _)) {
 95             if (_[0] < -PI) {
 96                 ev[tt++] = Event(_[0] + 2 * PI, 1);
 97                 ev[tt++] = Event(PI, -1);
 98                 ev[tt++] = Event(-PI, 1);
 99                 ev[tt++] = Event(_[1], -1);
100             } else if (_[1] > PI) {
101                 ev[tt++] = Event(_[0], 1);
102                 ev[tt++] = Event(PI, -1);
103                 ev[tt++] = Event(-PI, 1);
104                 ev[tt++] = Event(_[1] - 2 * PI, -1);
105             } else {
106                 ev[tt++] = Event(_[0], 1);
107                 ev[tt++] = Event(_[1], -1);
108             }
109         }
110     }
111     int cnt = 1, mx = 1;
112     sort(ev, ev + tt, cmp);
113     for (int i = 0; i < tt; i++) {
114         cnt += ev[i].y;
115         mx = max(mx, cnt);
116     }
117     return mx;
118 }
119 
120 int work() {
121     int mx = 0;
122     for (int i = 0; i < n; i++) mx = max(mx, cal(i));
123     return mx;
124 }
125 
126 int main() {
127     //freopen("in", "r", stdin);
128     ios::sync_with_stdio(0);
129     cout << setiosflags(ios::fixed) << setprecision(5);
130     int _;
131     cin >> _;
132     while (_--) {
133         input();
134         cout << work() << endl;
135     }
136     return 0;
137 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/hdu_1077_Lyon.html