1.首先將所有點隨機排列;2.按順序依次將點加入已經建好的圓中,每新增乙個點就進入步驟3;
3.如果點i在當前最小圓的外部,那麼說明點i一定在前i個點構成的最小圓的邊界上(因為要保證最小圓),進入步驟4處理;如果點i在當前最小圓的內部,則返回步驟2;
4.此時已經確定點i一定在前i個點所構成的最小圓的邊界上,則直接將點i作為圓心,半徑為0,重新將前i-1個點加入到這個圓中(類似上面的步驟,不過此時求的是包含點i的前j個點的最小覆蓋圓),每加乙個點就進入步驟5;
5.如果當前j點在最小圓外部,則說明點j一定在前j個點(包含點i)構成的最小圓的邊界上(與上類似),進入步驟6;否則不需要更新,返回4;
6.此時已經確定點i,j在前j個點(包括點i)構成的圓的邊界上,直接將圓心設為點i和j的中點,直徑為兩點距離,重新把前j-1個點加入到這個圓中,每加入乙個進入7;
7.如果當前點k在最小圓的外部,則點k在前k個點(包括i,j)構成的最小圓的邊界,此時i,j,k都在次圓邊界,直接3點共圓求出圓心與半徑即可;否則無需更新,返回6;
#include//o(n),最小圓覆蓋
#define ll long long
#define met(a, x) memset(a,x,sizeof(a))
#define inf 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
const double eps = 1e-12;
struct node s[500005];
node o;//圓心座標
double ri;//半徑
double dis(node a, node b)
void getr(node p1, node p2, node p3)
int main()
random_shuffle(s + 1, s + n + 1);
o = s[1];
ri = 0;
for (int i = 2; i <= n; i++) }}
}}
}cout << fixed << setprecision(10) << ri << endl;
cout << fixed << setprecision(10) << o.x << ' ' << fixed << setprecision(10) << o.y << endl;
return 0;
}
最小圓覆蓋
最小圓覆蓋。神奇的隨機演算法。當點以隨機的順序加入時期望複雜度是線性的。algorithm a 令ci表示為前i個點的最小覆蓋圓。當加入新點pi時如果pi不在ci 1裡那麼pi必定在ci的邊界上。b 再從新考慮這樣乙個問題,ci為前i個點最小覆蓋圓且p在ci的的邊界上!同理加入新點pi時如果p i不...
最小圓覆蓋
最小圓覆蓋問題 在乙個平面上,給出 n 個點,求包圍這些點的最小圓,輸出圓心及半徑。分析雖然可以用模擬退火或者三分套三分,這裡只講隨機增量法,隨機增量法是一種確定性演算法,隨機意義下均攤複雜度 o n 而且可以達到很高的精度 可達到 10 10 量級 有事實 如果點 p 不在集合 s 的最小圓覆蓋內...
最小圓覆蓋
本來不想學的 於是今天就碰到一道大裸題 例題 bzoj2823 求最小圓覆蓋n個點。偽 如下 把所有點隨機化,設為 x 1 y 1 x n y n 開始把圓心設為x 1 半徑設為0 for i 2ton 如果i號點在當前圓內則跳過 那麼i號點就在圓周上 把1號點和i號點作為直徑作乙個圓 for j ...