zoukankan      html  css  js  c++  java
  • 4818 Largest Empty Circle on a Segment (几何+二分)

    ACM-ICPC Live Archive

      挺水的一道题,直接二分圆的半径即可。1y~

      类似于以前半平面交求核的做法,假设半径已经知道,我们只需要求出线段周围哪些位置是不能放置圆心的即可。这样就转换为圆与直线,直线与直线交的问题了。

      不知道这题能不能SAA过,有空试下。

    代码如下:

      1 #include <cmath>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <iostream>
      6 #include <algorithm>
      7 
      8 using namespace std;
      9 
     10 const double EPS = 1e-5;
     11 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     12 typedef pair<double, double> Point;
     13 #define x first
     14 #define y second
     15 template<class T> T sqr(T x) { return x * x;}
     16 Point operator + (Point a, Point b) { return Point(a.x + b.x, a.y + b.y);}
     17 Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y);}
     18 Point operator * (Point a, double p) { return Point(a.x * p, a.y * p);}
     19 Point operator / (Point a, double p) { return Point(a.x / p, a.y / p);}
     20 
     21 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
     22 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
     23 inline double veclen(Point a) { return sqrt(dot(a, a));}
     24 inline Point vecunit(Point a) { return a / veclen(a);}
     25 inline Point normal(Point a) { return Point(-a.y, a.x) / veclen(a);}
     26 
     27 struct Line {
     28     Point s, t;
     29     Line() {}
     30     Line(Point s, Point t) : s(s), t(t) {}
     31     Point vec() { return t - s;}
     32     Point point(double p) { return s + vec() * p;}
     33     Line move(double p) { // + left - right
     34         Point nor = normal(vec());
     35         return Line(s + nor * p, t + nor * p);
     36     }
     37 } ;
     38 
     39 inline bool between(Point o, Point a, Point b) { return sgn(dot(a - o, b - o)) < 0;}
     40 inline bool between(Point a, Line l) { return between(a, l.s, l.t);}
     41 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
     42 
     43 bool clint(Point a, double r, double *sol) {
     44     if (sgn(r - fabs(a.y)) <= 0) return 0;
     45     double d = sqrt(sqr(r) - sqr(a.y));
     46     //cout << "d " << d << endl;
     47     sol[0] = a.x - d;
     48     sol[1] = a.x + d;
     49     return 1;
     50 }
     51 
     52 Line Y0 = Line(Point(0, 0), Point(1, 0));
     53 
     54 double L;
     55 inline void adjust(double &x) { x = max(0.0, min(L, x));}
     56 Point getseg(Line a, double r) {
     57     vector<double> sol;
     58     sol.clear();
     59     double t[2];
     60     if (clint(a.s, r, t)) sol.push_back(t[0]), sol.push_back(t[1]);
     61     if (clint(a.t, r, t)) sol.push_back(t[0]), sol.push_back(t[1]);
     62     Line l1 = a.move(r), l2 = a.move(-r), l3 = Line(l1.s, l2.s), l4 = Line(l1.t, l2.t);
     63     Point p1 = llint(l1, Y0), p2 = llint(l2, Y0), p3 = llint(l3, Y0), p4 = llint(l4, Y0);
     64     if (between(p1, l1)) sol.push_back(p1.x);
     65     if (between(p2, l2)) sol.push_back(p2.x);
     66     if (between(p3, l3)) sol.push_back(p3.x);
     67     if (between(p4, l4)) sol.push_back(p4.x);
     68     if (sol.size() == 0) return Point(-1, -1);
     69     sort(sol.begin(), sol.end());
     70     //cout << "sol ";
     71     //for (int i = 0; i < sol.size(); i++) cout << sol[i] << ' '; cout << endl;
     72     adjust(sol[0]), adjust(sol[sol.size() - 1]);
     73     return Point(sol[0], sol[sol.size() - 1]);
     74 }
     75 
     76 const int N = 2222;
     77 typedef pair<double, int> Event;
     78 Line l[N];
     79 int n;
     80 
     81 bool test(double r) {
     82     vector<Event> ev;
     83     ev.clear();
     84     for (int i = 0; i < n; i++) {
     85         Point tmp = getseg(l[i], r);
     86         if (tmp.x < 0 || tmp.y < 0) continue;
     87         //cout << tmp.x << '~' << tmp.y << endl;
     88         ev.push_back(Event(tmp.x, 1));
     89         ev.push_back(Event(tmp.y, -1));
     90     }
     91     sort(ev.begin(), ev.end());
     92     //cout << r << endl;
     93     //for (int i = 0; i < ev.size(); i++) cout << ev[i].x << '&' << ev[i].y << ' '; cout << endl;
     94     double last = 0;
     95     int cnt = 0, sz = ev.size();
     96     for (int i = 0; i < sz; i++) {
     97         if (ev[i].y == 1) {
     98             if (cnt == 0 && sgn(ev[i].x - last) > 0) return 1;
     99             cnt++;
    100         } else {
    101             if (cnt == 1) last = ev[i].x;
    102             cnt--;
    103         }
    104     }
    105     return sgn(L - last) > 0;
    106 }
    107 
    108 int main() {
    109     //freopen("in", "r", stdin);
    110     int T;
    111     cin >> T;
    112     while (T-- && cin >> n >> L) {
    113         for (int i = 0; i < n; i++) cin >> l[i].s.x >> l[i].s.y >> l[i].t.x >> l[i].t.y;
    114         double lp = 0, rp = 222222, mp;
    115         while (rp - lp > EPS) {
    116             mp = (lp + rp) / 2;
    117             if (test(mp)) lp = mp;
    118             else rp = mp;
    119         }
    120         //puts("~~~~~~~~~~~~~~~~~~~~~~~~");
    121         //test(2.118);
    122         printf("%.3f
    ", mp);
    123     }
    124     return 0;
    125 }
    View Code

    ——written by Lyon

  • 相关阅读:
    Linux三剑客awk命令试题
    Linux综合练习题
    Linux系统用户角色划分
    Linux添加磁盘fdisk命令
    Linux的七种运行级别
    Linux 文件类型
    Linux开机启动程序
    Linux软件安装
    linux运行级别
    Linux /etc目录下的重要配置文件
  • 原文地址:https://www.cnblogs.com/LyonLys/p/LA_4818_Lyon.html
Copyright © 2011-2022 走看看