P2533 [AHOI2012]訊號塔 P1742 最小圓覆蓋
阿新 • • 發佈:2021-10-26
只會隨機增量法
正確性:
顯然,這個圓一定是某兩個點的外接圓或者某個三角形的外接圓 ,否則就可以變得更小了
時間複雜度 期望是\(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相減可以得到
#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