最小圓覆蓋演算法

2021-07-17 04:28:49 字數 2141 閱讀 4323

演算法目的

演算法步驟

①首先現將所有點隨機排列

②按順序把點乙個乙個的加入(一步一步的求前i個點的最小覆蓋圓),每加入乙個點就進入③

③如果發現當前i號點在當前的最小圓的外面,那麼說明點i一定在前i個點的最小覆蓋圓邊界上,我們轉到④來進一步確定這個圓,否則前i個點的最小覆蓋圓與前i-1個點的最小覆蓋圓是一樣的,則不需要更新,返回②

④此時已經確認點i一定在前i個點的最小覆蓋圓的邊界上了,那麼我們可以把當前圓的圓心設為第i個點,半徑為0,然後重新把前i-1個點加入這個圓中(類似上面的步驟,只不過這次我們提前確定了點i在圓上,目的是一步一步求出包含點i的前j個點的最小覆蓋圓),每加入乙個點就進入⑤

⑤如果發現當前j號點在當前的最小圓的外面,那麼說明點j也一定在前j個點(包括i)的最小覆蓋圓邊界上,我們轉到⑥來再進一步確定這個圓,否則前j個點(包括i)的最小覆蓋圓與前i-1個點(包括i)的最小覆蓋圓是一樣的,則不需要更新,返回④

⑥此時已經確認點i,j一定在前j個點(包括i)的最小覆蓋圓的邊界上了,那麼我們可以把當前圓的圓心設為第i個點與第j的點連線的中點,半徑為到這兩個點的距離(就是找乙個覆蓋這兩個點的最小圓),然後重新把前j-1個點加入這個圓中(還是類似上面的步驟,只不過這次我們提前確定了兩個點在圓上,目的是求出包含點i,j的前k個點的最小覆蓋圓),每加入乙個點就進入⑦

⑦如果發現當前k號點在當前的最小圓的外面,那麼說明點k也一定在前k個點(包括i,j)的最小覆蓋圓邊界上,我們不需要再進一步確定這個圓了(因為三個點能確定乙個圓!),直接求出這三點共圓,否則前k個點(包括i,j)的最小覆蓋圓與前k-1個點(包括i,j)的最小覆蓋圓是一樣的,則不需要更新。

時間複雜度:o(n)

空間複雜度:o(n)

複雜度證明:空間複雜度顯然,下面來證時間複雜度

首先,因為我們已經將點打亂順序,所以我們可以認為點是隨機生成的

我們知道,當點完全隨機時,第i個點在前i-1個點的最小覆蓋圓外的機率是3/i

證明:我們先隨機生成i個點,求出他們的最小覆蓋圓,我們可以認為這個圓是由現在在邊界上的那三個點來確定的,也就是說當隨機生成的最後乙個點不是那三個點時,新生成的點就在圓內,否則在圓外,所以第i個點在前i-1個點的最小覆蓋圓外的概率只有3/i
所以o(

②)=∑

i=1i

≤n(i

−3i∗

o(1)

+3i∗

o(④)

) 而

o(④)

=∑i=

1i≤n

(i−3

i∗o(

1)+3

i∗o(

⑥))

易知o(

⑥)=o

(n)

所以可以推出,這個做法是線性的

注意事項:

以上時間複雜度的證明全部基於點的排列隨機,如果點的排列不隨機,那麼時間複雜度將有可能達到o(

n3)

所以最小圓覆蓋演算法只能在o(n)時間內求出n的點的最小覆蓋圓,而不能在o(n)的時間內求出所有的前i個點的最小覆蓋圓

下面是一段給定n個點求最小覆蓋圓圓心及半徑的**(bzoj1336/1337)

#include

#include

#include

#include

#include

#define n 100010

using namespace std;

struct nodeb[n];

node o;

double r;

double s

qr(double x)

double dis(node x,node y)

bool incircle(node x)

node solve(double a,double b,double c,double d,double e,double f);}

int main()}}

printf("%.10lf\n%.10lf %.10lf",r,o.x,o.y);

}

最小圓覆蓋

最小圓覆蓋。神奇的隨機演算法。當點以隨機的順序加入時期望複雜度是線性的。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 ...