zoukankan      html  css  js  c++  java
  • POJ 3525/UVA 1396 Most Distant Point from the Sea(二分+半平面交)

    Description

    The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is natural to ask a question: “Where is the most distant point from the sea?” The answer to this question for Honshu was found in 1996. The most distant point is located in former Usuda Town, Nagano Prefecture, whose distance from the sea is 114.86 km.

    In this problem, you are asked to write a program which, given a map of an island, finds the most distant point from the sea in the island, and reports its distance from the sea. In order to simplify the problem, we only consider maps representable by convex polygons.

    Input

    The input consists of multiple datasets. Each dataset represents a map of an island, which is a convex polygon. The format of a dataset is as follows.

    n    
    x1   y1
       
    xn   yn

    Every input item in a dataset is a non-negative integer. Two input items in a line are separated by a space.

    n in the first line is the number of vertices of the polygon, satisfying 3 ≤ n ≤ 100. Subsequent n lines are the x- and y-coordinates of the n vertices. Line segments (xiyi)–(xi+1yi+1) (1 ≤ i ≤ n − 1) and the line segment (xnyn)–(x1y1) form the border of the polygon in counterclockwise order. That is, these line segments see the inside of the polygon in the left of their directions. All coordinate values are between 0 and 10000, inclusive.

    You can assume that the polygon is simple, that is, its border never crosses or touches itself. As stated above, the given polygon is always a convex one.

    The last dataset is followed by a line containing a single zero.

    Output

    For each dataset in the input, one line containing the distance of the most distant point from the sea should be output. An output line should not contain extra characters such as spaces. The answer should not have an error greater than 0.00001 (10−5). You may output any number of digits after the decimal point, provided that the above accuracy condition is satisfied.

    题目大意:逆时针给出一个凸多边形,求一个点,问这个点离凸多边形的边最远是多少。

    思路:二分答案d,然后每条边向内平移d,看能否缩成一个点。

    代码(POJ 32MS/UVA 22MS):

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 using namespace std;
      7 
      8 const int MAXN = 110;
      9 const double EPS = 1e-8;
     10 const double PI = acos(-1.0);//3.14159265358979323846
     11 
     12 inline int sgn(double x) {
     13     return (x > EPS) - (x < -EPS);
     14 }
     15 
     16 struct Point {
     17     double x, y, ag;
     18     Point() {}
     19     Point(double x, double y): x(x), y(y) {}
     20     void read() {
     21         scanf("%lf%lf", &x, &y);
     22     }
     23     bool operator == (const Point &rhs) const {
     24         return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0;
     25     }
     26     bool operator < (const Point &rhs) const {
     27         if(y != rhs.y) return y < rhs.y;
     28         return x < rhs.x;
     29     }
     30     Point operator + (const Point &rhs) const {
     31         return Point(x + rhs.x, y + rhs.y);
     32     }
     33     Point operator - (const Point &rhs) const {
     34         return Point(x - rhs.x, y - rhs.y);
     35     }
     36     Point operator * (const int &b) const {
     37         return Point(x * b, y * b);
     38     }
     39     Point operator / (const int &b) const {
     40         return Point(x / b, y / b);
     41     }
     42     double length() const {
     43         return sqrt(x * x + y * y);
     44     }
     45     Point unit() const {
     46         return *this / length();
     47     }
     48 };
     49 typedef Point Vector;
     50 
     51 double dist(const Point &a, const Point &b) {
     52     return (a - b).length();
     53 }
     54 
     55 double cross(const Point &a, const Point &b) {
     56     return a.x * b.y - a.y * b.x;
     57 }
     58 //ret >= 0 means turn left
     59 double cross(const Point &sp, const Point &ed, const Point &op) {
     60     return sgn(cross(sp - op, ed - op));
     61 }
     62 
     63 double area(const Point& a, const Point &b, const Point &c) {
     64     return fabs(cross(a - c, b - c)) / 2;
     65 }
     66 
     67 struct Seg {
     68     Point st, ed;
     69     double ag;
     70     Seg() {}
     71     Seg(Point st, Point ed): st(st), ed(ed) {}
     72     void read() {
     73         st.read(); ed.read();
     74     }
     75     void makeAg() {
     76         ag = atan2(ed.y - st.y, ed.x - st.x);
     77     }
     78 };
     79 typedef Seg Line;
     80 
     81 void moveRight(Line &v, double r) {
     82     double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y;
     83     dx = dx / dist(v.st, v.ed) * r;
     84     dy = dy / dist(v.st, v.ed) * r;
     85     v.st.x += dy; v.ed.x += dy;
     86     v.st.y -= dx; v.ed.y -= dx;
     87 }
     88 
     89 bool isOnSeg(const Seg &s, const Point &p) {
     90     return (p == s.st || p == s.ed) ||
     91         (((p.x - s.st.x) * (p.x - s.ed.x) < 0 ||
     92           (p.y - s.st.y) * (p.y - s.ed.y) < 0) &&
     93          sgn(cross(s.ed, p, s.st) == 0));
     94 }
     95 
     96 bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) {
     97     return (max(s1.x, e1.x) >= min(s2.x, e2.x)) &&
     98         (max(s2.x, e2.x) >= min(s1.x, e1.x)) &&
     99         (max(s1.y, e1.y) >= min(s2.y, e2.y)) &&
    100         (max(s2.y, e2.y) >= min(s1.y, e1.y)) &&
    101         (cross(s2, e1, s1) * cross(e1, e2, s1) >= 0) &&
    102         (cross(s1, e2, s2) * cross(e2, e1, s2) >= 0);
    103 }
    104 
    105 bool isIntersected(const Seg &a, const Seg &b) {
    106     return isIntersected(a.st, a.ed, b.st, b.ed);
    107 }
    108 
    109 bool isParallel(const Seg &a, const Seg &b) {
    110     return sgn(cross(a.ed - a.st, b.ed - b.st)) == 0;
    111 }
    112 
    113 //return Ax + By + C =0 's A, B, C
    114 void Coefficient(const Line &L, double &A, double &B, double &C) {
    115     A = L.ed.y - L.st.y;
    116     B = L.st.x - L.ed.x;
    117     C = L.ed.x * L.st.y - L.st.x * L.ed.y;
    118 }
    119 //point of intersection
    120 Point operator * (const Line &a, const Line &b) {
    121     double A1, B1, C1;
    122     double A2, B2, C2;
    123     Coefficient(a, A1, B1, C1);
    124     Coefficient(b, A2, B2, C2);
    125     Point I;
    126     I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1);
    127     I.y =   (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);
    128     return I;
    129 }
    130 
    131 bool isEqual(const Line &a, const Line &b) {
    132     double A1, B1, C1;
    133     double A2, B2, C2;
    134     Coefficient(a, A1, B1, C1);
    135     Coefficient(b, A2, B2, C2);
    136     return sgn(A1 * B2 - A2 * B1) == 0 && sgn(A1 * C2 - A2 * C1) == 0 && sgn(B1 * C2 - B2 * C1) == 0;
    137 }
    138 
    139 struct Poly {
    140     int n;
    141     Point p[MAXN];//p[n] = p[0]
    142     void init(Point *pp, int nn) {
    143         n = nn;
    144         for(int i = 0; i < n; ++i) p[i] = pp[i];
    145         p[n] = p[0];
    146     }
    147     double area() {
    148         if(n < 3) return 0;
    149         double s = p[0].y * (p[n - 1].x - p[1].x);
    150         for(int i = 1; i < n; ++i)
    151             s += p[i].y * (p[i - 1].x - p[i + 1].x);
    152         return s / 2;
    153     }
    154 };
    155 
    156 void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top]
    157     sort(p, p + n);
    158     top = 1;
    159     stk[0] = 0; stk[1] = 1;
    160     for(int i = 2; i < n; ++i) {
    161         while(top && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top;
    162         stk[++top] = i;
    163     }
    164     int len = top;
    165     stk[++top] = n - 2;
    166     for(int i = n - 3; i >= 0; --i) {
    167         while(top != len && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top;
    168         stk[++top] = i;
    169     }
    170 }
    171 //use for half_planes_cross
    172 bool cmpAg(const Line &a, const Line &b) {
    173     if(sgn(a.ag - b.ag) == 0)
    174         return sgn(cross(b.ed, a.st, b.st)) < 0;
    175     return a.ag < b.ag;
    176 }
    177 //clockwise
    178 bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) {
    179     int i, n;
    180     sort(v, v + vn, cmpAg);
    181     for(i = n = 1; i < vn; ++i) {
    182         if(sgn(v[i].ag - v[i-1].ag) == 0) continue;
    183         v[n++] = v[i];
    184     }
    185     int head = 0, tail = 1;
    186     deq[0] = v[0], deq[1] = v[1];
    187     for(i = 2; i < n; ++i) {
    188         if(isParallel(deq[tail - 1], deq[tail]) || isParallel(deq[head], deq[head + 1]))
    189             return false;
    190         while(head < tail && sgn(cross(v[i].ed, deq[tail - 1] * deq[tail], v[i].st)) > 0)
    191             --tail;
    192         while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + 1], v[i].st)) > 0)
    193             ++head;
    194         deq[++tail] = v[i];
    195     }
    196     while(head < tail && sgn(cross(deq[head].ed, deq[tail - 1] * deq[tail], deq[head].st)) > 0)
    197         --tail;
    198     while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + 1], deq[tail].st)) > 0)
    199         ++head;
    200     if(tail <= head + 1) return false;
    201     res.n = 0;
    202     for(i = head; i < tail; ++i)
    203         res.p[res.n++] = deq[i] * deq[i + 1];
    204     res.p[res.n++] = deq[head] * deq[tail];
    205     res.n = unique(res.p, res.p + res.n) - res.p;
    206     res.p[res.n] = res.p[0];
    207     return true;
    208 }
    209 
    210 /*******************************************************************************************/
    211 
    212 Point p[MAXN];
    213 Poly poly;
    214 int stk[MAXN], top;
    215 int n, T;
    216 
    217 Poly res;
    218 
    219 Line original[MAXN], newLine[MAXN], deq[MAXN];
    220 
    221 bool check(double r) {
    222     for(int i = 0; i < n; ++i) newLine[i] = original[i];
    223     for(int i = 0; i < n; ++i) moveRight(newLine[i], r);
    224     return half_planes_cross(newLine, n, res, deq);
    225 }
    226 
    227 int main() {
    228     while(scanf("%d", &n) != EOF && n) {
    229         for(int i = 0; i < n; ++i) p[i].read();
    230         p[n] = p[0];
    231         for(int i = 0; i < n; ++i) original[i] = Line(p[i + 1], p[i]);
    232         for(int i = 0; i < n; ++i) original[i].makeAg();
    233         double l = 0, r = 1e9;
    234         for(int i = 0; i < 100; ++i) {
    235             double mid = (l + r) / 2;
    236             if(check(mid)) l = mid;
    237             else r = mid;
    238         }
    239         printf("%.10f
    ", l);
    240     }
    241 }
    View Code
  • 相关阅读:
    110. 平衡二叉树-前序遍历-简单
    207. 课程表-有向图判断有无环状-中等难度
    java错误集锦
    199. 二叉树的右视图-二叉树,dfs,从右往左遍历-中等难度
    114. 二叉树展开为链表-二叉树,dfs-中等难度
    236. 二叉树的最近公共祖先-中序遍历-中等难度
    Kendo ui 入门知识点
    Css样式压缩、美化、净化工具 源代码
    Linq与Lambda常用查询语法
    15个超强悍的CSS3圆盘时钟动画赏析
  • 原文地址:https://www.cnblogs.com/oyking/p/3416510.html
Copyright © 2011-2022 走看看