【模板】最小圆覆盖
三点定圆
已知三个不在同一直线上的点 \((x_1, y_1), (x_2, y_2), (x_3, y_3)\)。请确定过此三点的圆的圆心。
设圆心为 \((x, y)\),半径为 \(r\),则圆的方程为
展开得到
我们并不需要现在得知 \(r\) 的具体值,即我们并不关心 \(r^2\)。不妨把未知数的平方项合并为一个常数 \(C\)。
即我们现在需要求这个方程组的解:
根据克莱默法则,我们只需要求三个三阶行列式。
考虑到这三个行列式的最右边都是一列 \(1\),不妨将行列式沿着 \(1\) 展开,如:
也就稍微好写一点点。
最小圆覆盖
先看算法流程:
shuffle(a + 1, a + n + 1, mt19937{random_device{}()});
dot O = a[1];
double r = 0;
for (int i = 2; i <= n; i++) {
if (dis(a[i], O) - r < eps) continue; // 在圆内
O = a[i], r = 0;
for (int j = 1; j < i; j++) {
if (dis(a[j], O) - r < eps) continue;
O = (a[i] + a[j]) / 2, r = dis(a[i], a[j]) / 2;
for (int k = 1; k < j; k++) {
if (dis(a[k], O) - r < eps) continue;
O = minCircle(a[i], a[j], a[k]), r = dis(O, a[i]);
}
}
}
注意枚举顺序,\(i, j, k\) 都是从小往大枚举。
正确性证明
https://www.luogu.com.cn/article/8imn9rtw 不想抄了。这里补充最后一步的依据,是这个引理。
存在 \(𝑁,𝑀∈{𝐼,𝐽,𝐾}\) 且 \(𝑁≠𝑀\),使得 \(circle({𝑁,𝑀,𝑃})\) 包含这四个点。
因为另外几组点都说不可能了,那么一定是剩下这一组了。
时间复杂度证明
根据引理
对于一个 \(n\) 个点随机的序列,因为三点定一个圆,所以每一个点有 \(3/n\) 的概率成为更新这些点的最小圆覆盖的点(点会出现在新的圆上)。
可以发现,对于固定的 \(i,j\) 且 \(j\) 更新了最小圆,时间复杂度为 \(O(j)\);撤去 \(j\) 的固定,发现只有 \(O(i\times 3/i)=O(1)\) 个 \(j\) 会触发时间复杂度 \(O(j)\) 的循环,所以固定 \(i\) 且 \(i\) 更新了最小圆的时间复杂度为 \(O(i)\);撤去 \(i\) 个贡献同理,只有 \(O(n\times 3/n)=O(1)\) 个 \(i\) 会更新最小圆,故总的时间复杂度为 \(O(n)\)。
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/18322254/template-mincircle