演算法: Math, Computational Geometry
95/11/30 工具:座標系 必備武器:向量
點Points
兩個點的距離 (x1x2)2(y1y2)2
兩個點的向量(x2 x1,y2 y1)
向量內積Dot Products
兩個向量(a,b)和(c,d)的內積(a,b)(c,d)值為acbd 用途:判別角的大小、線段是否垂直
【例1】給定三角形頂點A,B,C的座標,請你判斷ABC是否為直角三角形。
向量外積Cross Products
平面上的向量(a,b)和(c,d)外積之值為
d c
b
det a = ad bc
外積值為0表示兩向量平行(collinear),值為正代表向量(a,b)在 )
,
(c d 的順時針方向。
【例2】設O為座標原點,平面上有兩個點P,Q。有一個機器人站在原點,面對P,現在他 要旋轉至面對Q,請問他應該向左轉或是向右轉?
【例3】給定一條直線的線上兩點P,Q,以及另外兩個點A,B,請你判斷A,B是否在直線
PQ的同一側?
【例4】某個人從點P0 出發,依序沿著線段PiPi1 走,試問走到Pn時,他左轉了多少次
右轉了多少次?
【例5】給你一個線段以及一個點,試判斷此點是否在線段上。
【例6】給你兩條線段P1P2 以及P3P4 ,請你判斷這兩條線段是否相交。 [ACM 378,191]
方法一:外積方法
Case 1: 若 P1,P2在線段P3P4 異側 且 P3,P4在線段P1P2 異側 ,那麼線段相交。
Case 2: 若 某個點在相對的另一條線段上,那麼線段相交。
方法二:純解析法(解方程)
算出兩直線交點位置,判斷這個交點是否在兩條線段上。
【例7】平面上給定n個點,請找出所有的三點共線。 [I2A 33.1-1,ACM 270]
多邊形Polygons
多邊形是由一些線段所組成的封閉折線。如果多邊形上的任兩條邊皆不相交,那麼此多 邊形稱為單純多邊形(simple polygon)。一個單純多邊形當中任意兩頂點之連線線段若全部 落在多邊形內,那麼我們稱這樣的多邊形為凸多邊形(convex polygon)。
在座標平面上計算多邊形的面積有簡單的公式可算。若一個多邊形的點依序為 )
, ( ), , ( ),..., ,
( ), ,
(x1 y1 x2 y2 xn yn xn1 yn1 ,其中xn1 x1,yn1 y1。那麼此多邊形的面積 為:
n ii i i
iy y x
x
1
1
2 1
1
【例8】依序給出一個n多邊形的n個頂點,請你判斷此多邊形是否為凸多邊形。
[ACM 10078]
【例9】給定一個多邊形以及一個點P,請你判斷此點是否在多邊形內部。 [ACM 634]
基本想法:過P作一條射線L,若L與多邊形交於奇數個點,那麼P在內部;若為偶數 個點則在外部。但是計算交點時要注意幾種情形:
Case 1 P1
P3
P4 P
2
Case 2 P1
P2
P3
P4
偶數個交點,但是在內部。
P
這這…到底交幾個點啊
。
Q
掃描法 Line Sweeping
掃描法也是計算幾何上常見的解題方法之一。通常是把所有的點先行依照某個特定的順 序排列(例如按照x座標排序),再由左至右或由右至左處理。
【例10】平面上兩個點(a,b)以及(x,y),我們說(x,y)支配(Dominate)了(a,b)若且唯 若xa且yb。給定平面上的
n
個點,請你找出所有的點,都不被其他n1個點支配[C名題百則5-16]
【例11】給定一些只垂直或平行於座標平面的線段,請你判斷是否存在兩線段相交。
顯然我們可以用O(n2)的時間求出答案,但是利用掃描法以及二分搜尋法可以加快速度。
【例12】給定一些線段,請你判斷這些線段之中是否有交點存在。
矩形覆蓋問題不只可以用Divide and Conquer做,還可以用掃描的。
【例13】座標平面上給定一些矩形,求總覆蓋面積。 [USACO 3.1 Shaping Regions, ACM
688]
不只是橫向掃描,有時候讓直線轉一圈也是不錯的辦法。
【例14】蛋糕上有一些草莓,其座標皆為整數。設蛋糕的中心是(0,0),請你切一刀過中心
並且讓兩邊蛋糕上的草莓數量相同。 [ACM 10167]
【例15】在一個大草原上,有一個多邊形牧場,牧場的每個邊都有個編號。請問,當你站
在(a,b)的位置的時候能夠看到多少條邊?假設光直線前進。 [USACO 3.4 Closed Fences]
【例16】第一象限上有一些線段,請問躺在x軸往上看,能看到多少線段? [94全國3]
凸包 Convex Hull
某個城市有許多重要的據點。現在因為軍事的需要,必須在城市外蓋城牆並至少把所有 據點都圍在城內,請問城牆的最小總長度為何?
【簡化過的問題】平面上一些點所形成的集合Q,請找到最小的凸多邊形P使得每個Q中 的點不是在P的邊上就是在P內部中。
【很基本的想法】用一條很緊的橡皮筋把所有點圈起來,放手之後就得到P了。
解這個問題的方法有很多,除了遞推法、分而治之以外,目前看起來最快的是排除法,
複雜度在一般情形下很接近線性(請參考I2A, P.952)。以下介紹另外兩種常用的方法:
Graham’s scan
將所有頂點依照逆時針順序放入一個堆疊中,並在過程中把確定不是凸包的點去除。
在詳細敘述這個演算法之前,先來證明一個東西:頂點集合Q中,y座標最小的點一定
是凸包上的頂點。以下是Graham’s scan的虛擬碼:
GRAHAM-SCAN(Q)
1 令p0表示Q中y座標最小的點,若有許多選擇那麼選x座標最小的點。
2 將其他的點X依照與p0X並且與正x軸夾角的大小由小至大排序,令為
pm
p
p1, 2,..., 。
3 PUSH(p0, S) //將p0放進堆疊S中,一開始S為空 4 PUSH(p1, S)
5 PUSH(p2, S) 6 for i ← 3 to m
7 do while 從堆疊中第二個點經過堆疊中最上面的點轉向至pi時非左轉
8 do POP(S) //將最上面的點拿出
9 PUSH(pi, S) 10 return S
Jarvis’s march
基本想法類似禮物包裝(gift wrapping)的方式。從底部的頂點p0開始,分成左邊和右 邊處理。處理右邊時,找到一個點p1使得p0p1與x軸夾角最小,顯然p1也屬於凸包;
以相同方式繼續尋找下一個點,直到找到的pk是Q中最高的點為止,完成右半邊。
左邊也用類似的方式處理即可。令h為凸包上頂點的總數,那麼這個演算法的複雜度 為O(nh),一般的狀況下h為o(lg n)此時Jarvis’s march會比Graham’s scan快。
[ACM 109, 10065]
最接近點對問題 Closet Pair
平面上有一些點形成集合Q,請在Q中找到兩個點,其距離是最小的。在這裡的距離,
指的是歐幾里得距離。O(n2)是個明顯的上界。但是很顯然的有些點對的距離不需要比較就 能確定不是最短的,是否有更快的方法呢?於是我們試著用Divide and Conquer解題。
將這個想法略寫如下:
令P為Q的子集合,是遞迴處理中的一部分。
如果P中點的個數不大於3個,那麼直接用三次比較即可找出最短距離。
Divide
選定一條鉛垂線l將點集P平均分成兩個子集PL和PR,其中PL為l左邊的點,PR為 l右邊的點,且兩邊點的個數要平均。
Conquer
假設PL的點對最短距離為L,PR中點對的最短距離為R。令 min(L,R)。 Combine
必須檢查由PL以及PR各一個點所連成的線段長度。但是因為兩個集合是以l分界,
故只要檢查l左右各 長度範圍內的點即可。我們希望花O(|P|)的時間在這上面,所
以這部份必須加快才行…詳情請參考I2A。
[ACM 10245]
皮克定理 Pick Theory
格子點:x,y座標值都是整數的點。
格子點和多邊形有著非比尋常的關係:
1. 直角座標系上一個所有頂點都是格子點的多邊形的面積的兩倍一定是整數。
2. 此多邊形的面積 = 多邊形內部的格子點數 + 多邊形邊上的格子點數 / 2 - 1
其中1.可以用之前提到的多邊形公式證得,2.就是皮克公式。
【例17】Farmer John只在格子點上放牛,請問一個三角形的牧場內能放多少牛?
[USACO 3.4 Electric Fence, ACM 11017]
應用題
【例18】最遠距離點對問題:請找出兩個點距離最遠。
Hint:這兩個點一定在凸包上(why?)
【例19】現在我們重新定義兩個點的距離:(x1,y1)和(x2,y2)的距離是
|
|
|
|x1x2 y1y2 (1)給定一些點的座標,請找出兩個點它們的距離最大。 [ACM 11012]
(2)在平面上找一個點P使得所有點到P的距離和最小。 [94全國2, 95北市4]
【例20】一個守衛站在美術館的大廳裡,美術館的大廳是一個單純多邊形,請問從守衛站
的地方能看到的大廳面積為何? [ACM 10907]
【例21】平面上有一些紅色點以及藍色點,是否存在一條直線將兩種顏色的點分開?
關於浮點數誤差的幾點建議…
1. 不要使用float,不管小數多麼單純
2. 整數轉浮點數的時候可以加上誤差值1e-9,可以減少一些不必要的困擾。例如 ACM10200。
3. 如果要判斷兩個浮點數p,q相不相等,可以把p==q改為fabs(p-q)<1e-9。
4. 盡量避免強制轉換變數型態。
最後…
儘管幾何演算法在競賽中並不是那麼重要,而且不管是在Coding或是思考時都比較繁瑣,
極容易拿到WA,不過偶爾還是得練一下。不建議在頭昏的時候寫這類程式。