1. 程式人生 > 其它 >P2533 [AHOI2012]訊號塔 P1742 最小圓覆蓋

P2533 [AHOI2012]訊號塔 P1742 最小圓覆蓋

只會隨機增量法

正確性:
顯然,這個圓一定是某兩個點的外接圓或者某個三角形的外接圓 ,否則就可以變得更小了

時間複雜度 期望是\(O(n)\)
我們先隨機生成i個點,求出他們的最小覆蓋圓,我們可以認為這個圓是由現在在邊界上的那三個點來確定的,也就是說當隨機生成的最後一個點不是那三個點時,新生成的點就在圓內,否則在圓外,所以第i個點在前i-1個點的最小覆蓋圓外的概率只有3/i
三個點,那麼期望就是O(n)咯,但是如果是特殊構造的資料可能卡到\(O(n^3)\)

貼下求三角形外接圓圓心座標的公式

\[\left\{\begin{array}{l} \left(x_{1}-x_{0}\right)^{2}+\left(y_{1}-y_{0}\right)^{2}=r^{2} (1)\\ \left(x_{2}-x_{0}\right)^{2}+\left(y_{2}-y_{0}\right)^{2}=r^{2} (2)\\ \left(x_{3}-x_{0}\right)^{2}+\left(y_{3}-y_{0}\right)^{2}=r^{2} (3) \end{array}\right. \]

1,2相減,1,3相減可以得到

\[ \begin{array}{l} \left(x_{1}-x_{2}\right) x_{0}+\left(y_{1}-y_{2}\right) y_{0}=\frac{\left(x_{1}^{2}-x_{2}^{2}\right)-\left(y_{2}^{2}-y_{1}^{2}\right)}{2} \\ \left(x_{1}-x_{3}\right) x_{0}+\left(y_{1}-y_{3}\right) y_{0}=\frac{\left(x_{1}^{2}-x_{3}^{2}\right)-\left(y_{3}^{2}-y_{1}^{2}\right)}{2} \end{array} \]\[\begin{array}{l} a=x_{1}-x_{2} \\ b=y_{1}-y_{2} \\ c=x_{1}-x_{3} \\ d=y_{1}-y_{3} \\ e=\frac{\left(x_{1}^{2}-x_{2}^{2}\right)-\left(y_{2}^{2}-y_{1}^{2}\right)}{2} \\ f=\frac{\left(x_{1}^{2}-x_{3}^{2}\right)-\left(y_{3}^{2}-y_{1}^{2}\right)}{2} \end{array} \]\[\begin{array}{l} x_{0}=\frac{d e-b f}{b c-a d} \\ y_{0}=\frac{a f-c e}{b c-a d} \end{array} \]
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i(j);i<=k;++i)
#define drp(i,j,k) for(int i(j);i>=k;--i)
#define repg(x) for(int i(G.head[x]);i;i=G.next[i])
#define bug cout<<"~~~~~~~~~~~~~"<<'\n';
using std::cin;
using std::cout;
typedef long long lxl;
template<typename T>
inline T  max( T a, T b) {
	return a > b ? a : b;
}
template<typename T>
inline T  min( T a, T b) {
	return a < b ? a : b;
}
std::mt19937 r(std::chrono::system_clock::now().time_since_epoch().count());
const int N = 1e6 + 79;
struct point {
	double x, y;
	point() {
		x = y = 0.0;
	}

} t[N], O; //Ô²ÐÄ

inline double dis(const point &rr,const point &r) {
	return sqrt( (rr.x - r.x) * (rr.x - r.x) + (rr.y - r.y) * (rr.y - r.y));
}


const double eps = 1e-6;
double R;
inline bool incircle(const point &x) {
	return dis(x, O) - R < eps;
}

inline point calc(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;
    
    point ans;
    ans.x=(a*f-b*e)/(2*a*d-2*b*c);
    ans.y=(d*e-c*f)/(2*a*d-2*b*c);
    R=dis(p1,ans);
    return ans;
}




int n;
int main() {
	std::ios::sync_with_stdio(false);

	cin >> n;
	rep(i, 1, n) {
		cin >> t[i].x >> t[i].y;
	}

	srand(r());
	std::random_shuffle(t + 1, t + n + 1);

	O = t[1];
	rep(i, 1, n) {
		if(incircle(t[i])) continue;
		O = t[i];
		rep(j, 1, i - 1) {
			if(incircle(t[j]))	 continue;
			O.x = (t[i].x + t[j].x) / 2.0;
			O.y = (t[i].y + t[j].y) / 2.0;
			R = dis(t[i], t[j]) / 2.0;

			rep(k, 1, j - 1) {
				if(incircle(t[k])) continue;
				{
					O = calc(t[i], t[j], t[k]);
					R = dis(O, t[i]);
				}

			}
		}
	}
	cout << std::fixed << std::setprecision(10) << R << '\n'<< O.x << ' ' << O.y << ' ' ;
	return 0;
}

本文來自部落格園,作者:{2519},轉載請註明原文連結:https://www.cnblogs.com/QQ2519/p/15465030.html