思路是通过求出与线段所在的直线的解析式垂直的直线斜率,然后带入求出解析式,求两条直线的交点,然后判断是不是在线段上,不在就从两个端点与当前点求距离取min,在就求当前点与交点的距离。
但是样例都过不去。。
#include <bits/stdc++.h>
#define pf(x) ((x) * (x))
#define DB long double
#define N 100010
using namespace std;
int n;
DB X[N], Y[N], ans, ax, ay;
inline DB Dis(DB xx1, DB yy1, DB xx2, DB yy2){return sqrt(pf(xx1 - xx2) + pf(yy1 - yy2));}
inline DB clac(int x, int y)
{
DB res = 0.0;
for(int i = 1; i <= n; i += 2)
{
DB k1 = (X[i + 1] - X[i]) / (Y[i + 1] - Y[i]);
DB b1 = Y[i] - k1 * X[i];
DB k2 = -1.0 / k1;
DB b2 = y - k2 * x;
DB xx = (b2 - b1) / (k1 - k2);
DB yy = k2 * xx + b2;
if(xx < X[i] || xx > X[i + 1])
{
res = max(res, min(Dis(x, y, X[i], Y[i]), Dis(x, y, X[i + 1], Y[i + 1])));
continue;
}
res = max(res, Dis(x, y, xx, yy));
}
printf("res : %.7Lf\n", res);
return res;
}
inline void SA()
{
DB T = 1e3;
DB xx = ax, yy = ay;
while(T > 1e-7)
{
DB tx = ((rand() * 1.0 / RAND_MAX) > 0.5 ? -1 : 1) * rand() * T * 1.0 / RAND_MAX;
DB ty = ((rand() * 1.0 / RAND_MAX) > 0.5 ? -1 : 1) * rand() * T * 1.0 / RAND_MAX;
if(fabs(xx + tx) > 1000.0 || fabs(yy + ty) > 1000.0) continue;
DB res = clac(xx + tx, yy + ty);
if(res < ans) ans = res, ax = xx = xx + tx, ay = yy = yy + ty;
else if(exp((ans - res) / T) * RAND_MAX > rand()) xx += tx, yy += ty;
T *= 0.997;
}
return ;
}
signed main()
{
srand(time(0));
cin >> n;
n <<= 1;
for(int i = 1; i <= n; i +=2)
{
cin >> X[i] >> Y[i] >> X[i + 1] >> Y[i + 1];
if(X[i] > X[i + 1]) swap(X[i], X[i + 1]), swap(Y[i], Y[i + 1]);
}
ax = ay = 500;
ans = clac(ax, ay);
SA();
printf("%.8Lf\n", ans);
return 0;
}