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 (xi, yi)–(xi+1, yi+1) (1 ≤ i ≤ n − 1) and the line segment (xn, yn)–(x1, y1) 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\n", l); 240 } 241 }