最小圓覆蓋

2022-02-02 08:42:41 字數 1810 閱讀 2465

本來不想學的…於是今天就碰到一道大裸題…

例題:bzoj2823 求最小圓覆蓋n個點。

偽**如下:

把所有點隨機化,設為(x[1],y[1

])...(x[n],y[n])

開始把圓心設為x[

1],半徑設為0

for i=2ton

如果i號點在當前圓內則跳過

//那麼i號點就在圓周上

把1號點和i號點作為直徑作乙個圓

for j=1

to i-1

如果j號點在當前圓內則跳過

考慮以j號點和i號點作為直徑作乙個圓

for k=1

to j-1

如果k號點在當前圓內則跳過

以i,j,k三點組成的三角形的外心作為新圓心

如果i,j,k三點共線就取ij、ik、jk連線最長的那條作為直徑作為新圓

據說期望複雜度是o(n)的。

細節還是比較多的。

首先共線叉積是比較容易判的。如果叉積為0那麼就共線。

那麼三角形的外心怎麼求呢?

如果有3個點,a(x1,y1),b(x2,y2),c(x3,y3)。

ab解析式:(y2-y1)x+(x1-x2)y+x2*y1-x1*y2=0

ab中點:((x1+x2)/2,(y1+y2)/2)

那麼ab中垂線解析式就是(y1-y2)x+(x1-x2)y+一些常數,把ab中點的座標帶進去減一下就行了。

然後我們求一下ab和ac中垂線的交點。

兩條直線

ax+by=c dx+ey=f

aex+bey=ce dbx+eby=fb

x=(fb-ce)/(ae-db)

同理adx+bdy=cd adx+aey=af

y=(af-cd)/(ae-bd)

當然如果ae=bd就共線。

所以就解決啦。

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

intn;

#define sz 2333333typedef

double

db;struct

pnt pnt(db a,db b)

}ps[sz];

pnt

operator - (pnt a,pnt b)

db operator * (pnt a,pnt b)

db pf(db x)

db dis(pnt a,pnt b)

pnt mid(pnt a,pnt b)

struct

lne lne(db x,db y,db z)

};pnt

operator *(lne a,lne b)

lne zcx(pnt a,pnt b)

pnt wx(pnt a,pnt b,pnt c)

db eps=1e-6

;pnt np(pnt a,pnt b,pnt c)

return

wx(a,b,c);

}db gr(pnt o,pnt a,pnt b,pnt c)

intmain()}}

printf(

"%.2lf %.2lf %.2lf\n

",yx.x,yx.y,r);

}

最小圓覆蓋

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

最小圓覆蓋

1.首先將所有點隨機排列 2.按順序依次將點加入已經建好的圓中,每新增乙個點就進入步驟3 3.如果點i在當前最小圓的外部,那麼說明點i一定在前i個點構成的最小圓的邊界上 因為要保證最小圓 進入步驟4處理 如果點i在當前最小圓的內部,則返回步驟2 4.此時已經確定點i一定在前i個點所構成的最小圓的邊界...