wenbao與最小圓覆蓋

2022-04-17 04:20:54 字數 3461 閱讀 8930

一下來自大神部落格:

這裡介紹的演算法是,先任意選取兩個點,以這兩個點的連線為直徑作圓。再以此判斷剩餘的點,看它們是否都在圓內(或圓上),如果都在,說明這個圓已經找到。如果沒有都在:假設我們用的最開始的兩個點為p[1],p[2],並且找到的第乙個不在圓內(或圓上)的點為p[i],於是我們用這個點p[i]去尋找覆蓋p[1]到p[i-1]的最小覆蓋圓。

那麼,過確定點p[i]的從p[1]到p[i-1]的最小覆蓋圓應該如何求呢?

我們先用p[1]和p[i]做圓,再從2到i-1判斷是否有點不在這個圓上,如果都在,則說明已經找到覆蓋1到i-1的圓。如果沒有都在:假設我們找到第乙個不在這個圓上的點為p[j],於是我們用兩個已知點p[j]與p[i]去找覆蓋1到j-1的最小覆蓋圓。

而對於兩個已知點p[j]與p[i]求最小覆蓋圓,只要從1到j-1中,第k個點求過p[k],p[j],p[i]三個點的圓,再判斷k+1到j-1是否都在圓上,若都在,說明找到圓;若有不在的,則再用新的點p[k]更新圓即可。

於是,這個問題就被轉化為若干個子問題來求解了。

由於三個點確定乙個圓,我們的過程大致上做的是從沒有確定點,到有乙個確定點,再到有兩個確定點,再到有三個確定點來求圓的工作。

a.通過三個點如何求圓?

先求叉積。

若叉積為0,即三個點在同一直線,那麼找到距離最遠的一對點,以它們的連線為直徑做圓即可;

若叉積不為0,即三個點不共線,那麼就是第二個問題,如何求三角形的外接圓?

b.如何求三角形外接圓?

假設三個點(x1,y1),(x2,y2),(x3,y3);

設過(x1,y1),(x2,y2)的直線l1方程為ax+by=c,它的中點為(midx,midy)=((x1+x2)/2,(y1+y2)/2),l1中垂線方程為a1x+b1y=c1;則它的中垂線方程中a1=-b=x2-x1,b1=a=y2-y1,c1=-b*midx+a*midy=((x2^2-x1^2)+(y2^2-y1^2))/2;

同理可以知道過(x1,y1),(x3,y3)的直線的中垂線的方程。

於是這兩條中垂線的交點就是圓心。

c.如何求兩條直線交點?

設兩條直線為a1x+b1y=c1和a2x+b2y=c2。

設乙個變數det=a1*b2-a2*b1;

如果det=0,說明兩直線平行;若不等於0,則求交點:x=(b2*c1 -b1*c2)/det,y=(a1*c2-a2*c1)/det;

d.於是木有了。。

大牛**:

1 #include2 #include3

struct

tpoint;

6 tpoint a[1005

],d;

7doubler;8

9double

distance(tpoint p1, tpoint p2)

12double

multiply(tpoint p1, tpoint p2, tpoint p0)

15void minidiscwith2point(tpoint p,tpoint q,int

n)30

else

36else

if(t2>=t1&&t2>=t3)

37

38else

39 40}

41}42}

4344

void minidiscwithpoint(tpoint pi,int

n)54}55

}56intmain()

64if(n==1

)65

66 r=distance(a[1],a[2])/2.0

;67 d.x=(a[1].x+a[2].x)/2.0

;68 d.y=(a[1].y+a[2].y)/2.0;69

for(i=3;i<=n;i++)

74 printf("

%.1lf %.1lf\n

",d.x,d.y);75}

76return0;

77 }

垃圾**:

1 #include 2 #include 3 #include 4

using

namespace

std;

5doubler;6

struct

node t[1005

], t;

9double

dis(node a, node b)

12double

xmup(node a, node b, node c)

15void findmin2(node a, node b, int

x)else34}

35}36void findmin(node a, int

x)44}45

intmain()

53if(m == 1

)57 t.x = (t[1].x + t[2].x) /2.0

;58 t.y = (t[1].y + t[2].y) /2.0

;59 r = dis(t[1], t[2]) /2.0;60

for(int i = 3; i <= m; i++)

64 printf("

%.1lf %.1lf\n

", t.x, t.y);65}

66return0;

67 }

1 #include 2 #include 3 #include 4

using

namespace

std;

5doubler;6

struct

nodet[505

], t;

9double

dis(node a, node b)

12double

xmup(node a, node b, node c)

15void findmin2(node a, node b, int

x)else34}

35}36void findmin(node a, int

x)44}45

intmain()

52if(n == 1

)56 t.x = (t[1].x + t[2].x) /2.0

;57 t.y = (t[1].y + t[2].y) /2.0

;58 r = dis(t[1], t[2]) /2.0;59

for(int i = 3; i <= n; i++)

63 printf("

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

", t.x, t.y, r);64}

65return0;

66 }

只有不斷學習才能進步!

最小圓覆蓋

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