題目很好理解:給你n個點,求其中距離最近的一對點(之間的距離)。
很顯然可以列舉,時間複雜度θ(
n2)如果資料強一點(n=100000什麼的),顯然列舉直接掛掉,那麼要怎麼辦呢?
這裡就要用到分治(當然是二分)了,時間複雜度θ(
nlog
2n)ps.以前幾乎沒做過分治,一來就碰到求最近點對這種題,我當時也看了1小時的題解才大概明白,當然我相信這篇部落格一定能讓你明白的~
首先,我們隨便來幾個點:
然後,將他們按x座標排個序,方便找x座標在中間的點,即編號為n/2的點。否則,例如上圖,編號n/2(即3)的點根本不在中間。
排序過後編號所對應的點就不同了,也可以理解為點的編號不同了,即:
這樣一來,想找x座標中間的點就是n/2了(雖然不能整除,但沒有問題)。
然後就可以直接由編號在中間的點二分了:
在s1裡面重複上述的操作(排序就不用了),直到只有1個點時,返回極大值(點對不可能只有乙個點),有兩個點時,返回這兩點的距離,很好理解。
然後再在s2裡重複一次。
(這裡的分治有遞迴的思想,實在無法理解的小夥伴自己多想想吧~我也沒有什麼辦法講得更詳細了……)
在得到s1和s2的答案後(當你遞迴到s1只有1個或2個點,s2也只有1個或2個點時,就需要從s1和s2的答案得到整體的答案了),首先想到:答案有可能是mi
n(an
ss1,
anss
2),這樣就是算左右區間中更小的答案。
但是,這只是ans中的兩個點都在一側(s1或s2)的情況,但是ans有可能乙個點在s1中,乙個點在s2,這就是這道題最最最噁心的乙個地方了
ps.接下來的一切極其燒腦,做好準備吧騷年設d
=min
(ans
s1,a
nss2
),則距離有可能小於d的兩個點p1,p2只有可能在下圖中的黑色直線之間:
圖1 那我就要問(當時這個問題我想了好久,真的不明白)了:為什麼不是在這個黑色直線之間呢?
圖2 事實上,p1和p2兩個點可以是這樣的:
圖3 顯然p1和p2的距離是小於d的,但p1並不在圖2的範圍內
好了,所以還需要把x座標在 mi
dx−d
到 mid
x+d 的點給挑出來。
然後怎麼辦?乙個乙個地列舉嗎?還是不行,這樣最壞的情況下可能會列舉到(n
2)2個點(這個你可以不用知道為什麼,只需要知道這樣很耗時就行了)
所以我們還需要優化一下,網上很多人說,對於點p1,和它的距離小於d的最多只有6個點,但我完全不懂,所以這裡就不這樣了。我們可以用這一條優化:先將之前說的範圍中的點挑出來後,按y座標從小到大排序,然後兩個迴圈列舉,但是,對於第二個點j,只要從第乙個點i+1開始列舉即可。然後,當點j與點i的距離大於了d時,就不用再列舉j了(再列舉j的y座標只會更大,與i的距離也會更大)。
演算法就是這樣了。
見【分治】【二分】poj 3714 raid
平面最近點對
求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2 ...
平面最近點對
求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對...
平面最近點對
求點集中的最近點對有以下兩種方法 設p1 x1,y1 p2 x2,y2 pn xn,yn 是平面上n個點構成的集合s,設計演算法找出集合s中距離最近的點對。1 蠻力法 適用於點的數目比較小的情況下 1 演算法描述 已知集合s中有n個點,一共可以組成n n 1 2對點對,蠻力法就是對這n n 1 2對...