曼哈顿距离最小生成树
一、參考博客
博客:曼哈頓距離最小生成樹與莫隊算法
博客:學習總結:最小曼哈頓距離生成樹
二、前置知識
1.曼哈頓距離:給定二維平面上的N個點,在兩點之間連邊的代價。(即distance(P1,P2) = |x1-x2|+|y1-y2|)
2.曼哈頓距離最小生成樹問題求什么?求使所有點連通的最小代價。
3.最小生成樹
三、具體實現方式
樸素的算法可以用O(N2)的Prim,或者處理出所有邊做Kruskal,但在這里總邊數有O(N2)條,所以Kruskal的復雜度變成了O(N2logN)。
但是事實上,真正有用的邊遠沒有O(N2)條。我們考慮每個點會和其他一些什么樣的點連邊。
可以得出這樣一個結論:以一個點為原點建立直角坐標系,在每45度內只會向距離該點最近的一個點連邊。
證明結論:假設我們以點A為原點建系,考慮在y軸向右45度區域內的任意兩點B(x1,y1)和C(x2,y2),不妨設|AB|≤|AC|(這里的距離為曼哈頓距離),如下圖:
|AB|=x1+y1,|AC|=x2+y2,|BC|=|x1-x2|+|y1-y2|。而由于B和C都在y軸向右45度的區域內,有y-x>0且x>0。下面我們分情況討論:
x1>x2且y1>y2。這與|AB|≤|AC|矛盾;
x1≤x2且y1>y2。此時|BC|=x2-x1+y1-y2,|AC|-|BC|=x2+y2-x2+x1-y1+y2=x1-y1+2y2。由前面各種關系可得y1>y2>x2>x1。假設|AC|<|BC|即y1>2y2+x1,那么|AB|=x1+y1>2x1+2y2,|AC|=x2+y2<2*y2<|AB|與前提矛盾,故|AC|≥|BC|;
x1>x2且y1≤y2。與2同理;
x1≤x2且y1≤y2。此時顯然有|AB|+|BC|=|AC|,即有|AC|>|BC|。
綜上有|AC|≥|BC|,也即在這個區域內只需選擇距離A最近的點向A連邊。
這種連邊方式可以保證邊數是O(N)的,那么如果能高效處理出這些邊,就可以用Kruskal在O(NlogN)的時間內解決問題。下面我們就考慮怎樣高效處理邊。
我們只需考慮在一塊區域內的點,其他區域內的點可以通過坐標變換“移動”到這個區域內。為了方便處理,我們考慮在y軸向右45度的區域。在某個點A(x0,y0)的這個區域內的點B(x1,y1)滿足x1≥x0且y1-x1>y0-x0。這里對于邊界我們只取一邊,但是操作中兩邊都取也無所謂。那么|AB|=y1-y0+x1-x0=(x1+y1)-(x0+y0)。在A的區域內距離A最近的點也即滿足條件的點中x+y最小的點。因此我們可以將所有點按x坐標排序,再按y-x離散,用線段樹或者樹狀數組維護大于當前點的y-x的最小的x+y對應的點。時間復雜度O(NlogN)。
至于坐標變換,一個比較好處理的方法是第一次直接做;第二次沿直線y=x翻轉,即交換x和y坐標;第三次沿直線x=0翻轉,即將x坐標取相反數;第四次再沿直線y=x翻轉。注意只需要做4次,因為邊是雙向的。
至此,整個問題就可以在O(NlogN)的復雜度內解決了。
【回到正題】
一個點把平面分成了8個部分:
由上面的廢話可知,我們只需要讓這個點與每個部分里距它最近的點連邊。
拿R1來說吧:
如圖,i的R1區域里距i最近的點是j。也就是說,其他點k都有:
xj + yj <= xk + yk
那么k將落在如下陰影部分:
顯然,邊(i,j), (j,k), (i,k)構成一個環<i,j,k>,而(i,k)一定是最長邊,可以被刪去。所以我們只連邊(i,j)。
為了避免重復加邊,我們只考慮R1~R4這4個區域。(總共加了4N條邊)
這4個區域的點(x,y)要滿足什么條件?
如果點(x,y)在R1,它要滿足:x ≥ xi ,y – x ≥ yi – xi(最近點的x + y最小)
如果點(x,y)在R2,它要滿足:y ≥ yi ,y – x ≤ yi – xi(最近點的x + y最小)
如果點(x,y)在R3,它要滿足:y ≤ yi ,y + x ≥ yi + xi(最近點的y – x最小)
如果點(x,y)在R4,它要滿足:x ≥ xi ,y + x ≤ yi – xi(最近點的y – x最小)
其中一個條件用排序,另一個條件用數據結構(這種方法很常用),在數據結構上詢問,找最近點。因為詢問總是前綴或后綴,所以可以用樹狀數組。
總結
以上是生活随笔為你收集整理的曼哈顿距离最小生成树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何查看ip地址
- 下一篇: 403 forbidden怎么解决?