题解:P2533 [AHOI2012] 信号塔
Dream_Stars · · 题解
方法一:随机增量法:
分析:用最小的圆覆盖住所有的点:随机增量法复杂度是
性质:在既定的给定点条件下,如果引入一张新的半平面,只要此前的最优解顶点(即唯一确定最小包围圆的几个关键顶点)能够包含于其中,则不必对此最优解进行修改,亦即此亦为新点集的最优解;否则,新的最优解顶点必然位于这个新的半空间的边界上。定理可以通过反证法证明。于是,基于此性质,我们便可得到一个类似于线性规划算法的随机增量式算法。
定义
则仿照上述处理的思路,
由于,三点唯一地确定一个圆,故而,只需在此基础上判断其他的点是否位于此包围圆内,不停地更新
总结: 假设圆
方法二:模拟退火法:
分析:对于每个枚举的点找到改点到所给点的最远点的距离,然后保证这个距离最小,即为所求圆的半径。
AC 代码(方法
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
const double eps = 1e-8;
struct Point {
double x, y;
} a[N], O;
double R;
double sqr(double x) {return x * x;}
double dis(Point a, Point b) {return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
void work(Point p1, Point p2, Point p3) {
double a, b, c, d, e, f;
a = p2.y - p1.y; b = p3.y - p1.y; c = p2.x - p1.x; d = p3.x - p1.x;
f = p3.x * p3.x + p3.y * p3.y - p1.x * p1.x - p1.y * p1.y;
e = p2.x * p2.x + p2.y * p2.y - p1.x * p1.x - p1.y * p1.y;
O.x = (a * f - b * e) / (2 * a * d - 2 * b * c); O.y = (d * e - c * f) / (2 * a * d - 2 * b * c);
R = dis(O, p1);
}
int main() {
int n;
scanf("%d", &n);
for (int i=1; i<=n; ++i) scanf("%lf%lf", &a[i].x, &a[i].y);
random_shuffle(a+1, a+n+1);
O=a[1]; R=0;
for (int i=2; i<=n; ++i)
if (dis(a[i], O) > R + eps) {
O = a[i]; R = 0;
for (int j=1; j<i; ++j)
if (dis(a[j], O) > R + eps) {
O.x = (a[i].x + a[j].x) / 2; O.y = (a[i].y + a[j].y) / 2; R = dis(a[j], O);
for (int k=1; k<j; ++k) if (dis(a[k], O) > R + eps) work(a[i], a[j], a[k]);
}
}
printf("%.2lf %.2lf %.2lf\n", O.x, O.y, R);
return 0;
}