Description

很久以前,在世界的某处有一个形状为凸多边形的小岛,岛上的居民们决定建一个祭坛,居民们任务祭坛的位置离岛的顶点处越远越好。 你的任务是求凸多边形内一点,使其与各顶点的距离中最短的距离最远,点在边上也可以。 这样的点可能有多个,你只需输出这些点与各顶点的最短距离。

Input

第一行是一个整数N(3<=N<=100)。 接下来N行按逆时针顺序给出每个顶点的坐标,每行包含2个实数,表示顶点的横坐标和纵坐标(坐标绝对值小于10000)。

Output

输出一个实数,表示凸多边形内一点与各顶点的距离中最短的距离的最大值(保留三位小数)。

Sample Input

1
2
3
4
3
0 2
9 0
7 7

Sample Output

1
4.893

题目大意

给出一个多边形,最大化一个点到各顶点的最短的距离,求最大化的最短距离

题解

从样例入手

此时,最大化的最短距离为这个三角形的外接圆的半径

这启示我们从圆入手

看到最大,最小,想到二分答案ansans

检验一个答案ansans是否正确,可以以每个顶点为圆心,ansans长为半径画弧,交多边形的边

假设当前的ansans33,那样例就变成了这样

此时发现区域cc,是没有被扇形覆盖的,由此可见,此时的ans=4ans=4是合法的

做一点简单的观察,EEFFIIHHDD点到AABBCC点的距离都大于ansans(由图易得)

这又启示我们从任意两点构造出来的扇形的交点来判断ansans的合法性

于是有了一些难点:


第一个是求扇形的交点

对于两个点AABB,有BD=AD=BE=AE=ansBD=AD=BE=AE=ans,则DEDE垂直平分ABAB

DD做水平竖直的线,易证DGFBCA\triangle DGF \sim \triangle BCA

由勾股定理,DFDF已知,由此可知DGDGGFGF

又知中点FF的坐标,因此可求交点DD坐标

同理得EE


第二个是没有交点

没有交点的话把GGHH,(扇形与多边形边的交点)当成交点就好啦

也是可以用相似求出点坐标的


第三个是判断扇形的交点是否在多边形以内

计算多边形的面积为SS

对于一个点EE,我们计算它与多边形的每一条边连成的三角形的面积的总和sumsum

显然,在第一个图中,EE在多边形的内部,sum=Ssum=S

在第二个图中,EE在多边形的外部,sum>Ssum>S

由此可以判断,扇形的交点是否在多边形内。


然后就没有啦~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <cmath>
#include <cstdio>
#define sqr(x) ((x)*(x))
#define dis(u,v,r,s) sqrt(sqr(u - r) + sqr(v - s))
using namespace std;
double l, r, mid, S, x[105], y[105]; int n;
double size(double u, double v, int i, int j) {
double t1 = (x[j] - x[i]), t2 = (y[j] - y[i]);
double r = (t1 * t1 * u + t2 * t2 * x[i] + v * t1 * t2 - y[i] * t2 * t1) / (t2 * t2 + t1 * t1);
double s = !t2 ? y[i] : -t1 * (r - u) / t2 + v;
double h = dis(u, v, r, s), d = sqrt(t1 * t1 + t2 * t2);
return (h * d / 2);
}
bool in(double u, double v) {
double sum = 0;
for (int i = 1; i <= n; ++i)
sum += size(u, v, i, i % n + 1);
return abs(S - sum) <= 10e-6;
}
bool check(double u, double v, double a) {
for (int k = 1; k <= n; ++k)
if (dis(u, v, x[k], y[k]) < a)
return 0; return 1;
}
bool ok(double a) {
for (int i = 1; i < n; ++i)
for (int j = i + 1; j <= n; ++j) {
double u = x[i] - x[j], x1, y1;
double v = y[i] - y[j], x2, y2;
double c = sqrt(u * u + v * v);
if (a < c / 2) {
x1 = x[j] + u * a / c, y1 = y[j] + v * a / c;
x2 = x[i] - u * a / c, y2 = y[i] - v * a / c;
} else {
double h = sqrt(a * a - c * c / 4);
x1 = (x[i] + x[j]) / 2 + v * h / c;
y1 = (y[i] + y[j]) / 2 - u * h / c;
x2 = (x[i] + x[j]) / 2 - v * h / c;
y2 = (y[i] + y[j]) / 2 + u * h / c;
}
if (in(x1, y1) && check(x1, y1, a)) return 1;
if (in(x2, y2) && check(x2, y2, a)) return 1;
}
return 0;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lf%lf", x + i, y + i);
for (int i = 1; i < n; ++i)
for (int j = i + 1; j <= n; ++j) {
double t = dis(x[i],y[i],x[j],y[j]);
if (t > r) r = t;
}
for (int i = 1; i < n - 1; ++i)
S += size(x[n], y[n], i, i + 1);
while (l + 10e-6 < r) {
mid = (l + r) / 2;
if (ok(mid)) l = mid; else r = mid;
}printf("%.3lf", l);
}