1. 程式人生 > 實用技巧 >最少的圓覆蓋點集的問題-貪心思想

最少的圓覆蓋點集的問題-貪心思想

最少的圓覆蓋點集的問題-貪心思想

問題

問題描述

假設海岸線是一條無限延伸的直線,陸地在海岸線的一側,海洋在另外一側。每個小島相當於海洋側的一個點。坐落在海岸線上的基站只能覆蓋半徑為d的範圍。應用直角座標系,將海岸線作為x軸,設海洋側在x軸上方。給定海洋中各小島的位置,以及通訊基站的覆蓋半徑,要求用最少的基站覆蓋所有小島,使得每個小島都能和陸地通過某基站通訊(在某個基站覆蓋範圍內)。

問題形式化定義

輸入

  • S = {S1,S2,...,Sn},半徑d

輸出

  • P = {P1,P2,...}

演算法描述

貪心思想

簡單來講,就是在對於Si畫圓,要求圓心在x軸上,且圓心應當處於Si右側,以及Si

在該圓上。我們所要關心的是圓與x軸的左交點的橫座標。

依據左交點橫座標的大小,對S集合中的點進行升序排列。依次處理排序後最前端的點Si,如果P中不存在圓容納Si,那麼將Si之前所畫圓的圓心容納入集合P中,否則,繼續處理下一個點。

舉例為:

如上圖,輸入小島座標S=[S2,S1,S4,S3],按照以各點為圓上一點時,該圓與x軸的左交點左至右(從小到大)排序後得到S=[S1,S2,S3,S4]。

開始作圓,從左至右,從S1開始,即先畫出黃圈,到S2,因為S2在上一圓內,故繼續;到S3,因S3在上一圓(黃圈)外,故保留上一圓(黃圈),另作新圓(藍圈),到S4,因S4在上一圓(藍圈)內,故繼續。
否則,如果只是按照x座標從左至右排序,即從S2開始作圓,到S1,S1並不在S2所作的紅圈內,故作新圓,如此產生多餘的圓。

分析貪心選擇性

定理, 存在一個原問題的最優解P,P點一定包含上述排序之後最前端點S0所畫圓的圓心y。

證明, 如果不存在這樣的最優解,包含S0所畫圓的圓心y。那麼對於該問題的任意一個最優解M而言,其一定存在一個圓心x,使得以x為圓心的點包含點S0。令N = (M/{x})U{y},N同樣是原問題的解。以y為圓心的圓一定可以包含僅由x為圓心的圓所包含的點(這一點是顯然的,也是無法證明的)。所以,|M|=|N|,M同樣是原問題的一個最優解,這與假設矛盾,所以假設不成立。

分析優化子結構

定理, 對於原問題的包含上述排序之後最前端點S0所畫圓的圓心y的最優解P而言,P/{y}是 S/{a|a∈P,且a包含在以y為圓心的圓內}的該問題的最優解。

證明, P/{y}不是 S/{a|a∈P,且a包含在以y為圓心的圓內}的該問題的最優解,那麼一定存在該問題的一個最優解D,|D|<|P/{y}|+1,這與P是原問題的最優解矛盾,假設不成立。,那麼,DU{y}一定是原問題的一個解,而|DU{y}|=|D|+ 1 > |P|=|P/{y}|+1,這與P是原問題的最優解矛盾,假設不成立。

演算法設計

Seclet-circle(P[1..n],d);
ascending sort P by p.x + sqrt(d*d - p.y*p.y) - d;
S = null;
vertex = null;
for i=0 to n do
    if S == null || dis(P[i],vertex) > d
       vertex = {P[i]所畫圓的圓心};
       S = SU{vertex};
return S;

演算法複雜性分析

O(nlogn) + O(n) = O(n).