FJ省队集训DAY1 T1

题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆。

思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会有交集,形如s0 s1 e0 e1

同样的,如果是n个点,那就是s0 s1 s2..sn e0 e1 e2.. en

因此,我们枚举那个起始点,然后对于其他点我们按照s排序,对于e做最长上升子序列即可。时间复杂度O(n^2 logn)

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 const double pi = 3.14159265358979324;
 6 double th1[2000], th2[2000], b[2000], x[2000], y[2000];
 7 std::pairdouble, double>, int> a[2000];
 8 int t[2001], t2[2001], f[2001], n;
 9 std::vector<int> ansv;
10 double r;
11 int main() {
12     freopen("crazy.in", "r", stdin);
13     freopen("crazy.out", "w", stdout);
14     scanf("%d%lf", &n, &r);
15     for (int i = 0; i < n; i++) {
16         scanf("%lf%lf", &x[i], &y[i]);
17         double th = atan2(y[i], x[i]);
18         double dth = acos(r / sqrt(x[i] * x[i] + y[i] * y[i]));
19         th1[i] = th + dth; if (th1[i] > pi) th1[i] -= 2*pi;
20         th2[i] = th - dth; if (th2[i] <= -pi) th2[i] += 2*pi;
21         if (th1[i] > th2[i]) std::swap(th1[i], th2[i]);
22     }
23     int ans = 1;
24     ansv.push_back(0);
25     for (int i = 0; i < n; i++) {
26         int l = 0, ans2 = -1;
27         for (int j = 0; j < n; j++)
28             if (i != j && (th1[j] < th1[i] || th1[j] > th2[i] || th2[j] < th1[i] || th2[j] > th2[i])
29                     && (th1[j] > th1[i] && th1[j] < th2[i] || th2[j] > th1[i] && th2[j] < th2[i])) {
30                 if (th1[j] > th1[i] && th1[j] < th2[i]) {
31                     a[l].first.first = th1[j] - th1[i];
32                     a[l].first.second = th2[j] - th2[i];
33                 } else {
34                     a[l].first.first = th2[j] - th1[i];
35                     a[l].first.second = th1[j] - th2[i];
36                 }
37                 if (a[l].first.second < 0) a[l].first.second += 2*pi;
38                 a[l].second = j;
39                 l++;
40             }
41         std::sort(a, a + l);
42         for (int j = 0; j < l; j++) b[j] = a[j].first.second;
43         std::sort(b, b + l);
44         for (int j = 1; j <= l; j++) t[j] = 0;
45         for (int j = 0; j < l; j++) {
46             int p = std::lower_bound(b, b + l, a[j].first.second) - b + 1;
47             int v = 0, v2 = -1;
48             for (int k = p; k; k -= k&-k)
49                 if (t[k] > v) v = t[k], v2 = t2[k];
50             v++;
51             f[a[j].second] = v2;
52             if (v+1 > ans) ans = v+1, ans2 = a[j].second;
53             for (int k = p; k <= l; k += k&-k)
54                 if (t[k] < v) t[k] = v, t2[k] = a[j].second;
55         }
56         if (ans2 != -1) {
57             ansv.clear();
58             while (ans2 != -1)
59                 ansv.push_back(ans2), ans2 = f[ans2];
60             ansv.push_back(i);
61         }
62     }
63     printf("%d\n", ans);
64     return 0;
65 }

 

转载于:https://www.cnblogs.com/qzqzgfy/p/5639063.html

你可能感兴趣的:(FJ省队集训DAY1 T1)