Geometriai algoritmusok Alapfogalmak Pont: (x,y) R R Szakasz: Legyen A,B két pont. Az A és B pontok által meghatározott szakasz: AB = {p = (x,y) : x = aa.x + (1 a)b.x,y = aa.y + (1 a)b.y),a R,0 a 1. Ha A és B sorrendje is számít, akkor irányított szakaszról beszélünk. Egyenes megadása: y = mx+b egyenlettel: azon (x,y) pontok halmaza, amelyekre teljesül az egyenlet, ax+by+c = 0 egyenlettel, egyenes megadása két pontjával: e(a,b). Az A B keresztszorzat a (0,0), A,B és a A + B = (A.x + B.x,A.y + B.y) pontok által alkotott paralelogramma előjeles területeként értelmezhető. Azaz A B = A.xB.y B.xA.y. A keresztszorzat alapján meghatározható a pontoknak az origóból vett egymáshoz viszonyított forgásiránya. Ha A B pozitív, akkor A az óramutató járásával egyező forgásirányba esik B-hez képest az origóból nézve. Ha A B negatív, akkor A az óramutató járásával ellentétes forgásirányba esik B-hez képest az origóból nézve. Ha A B = 0, akkor az origó, A és B egy egyenesen helyezkednek el. A fentiek alapján az is eldönthető, hogy egy AB irányított szakasz milyen forgásirányba esik egy AC szakaszhoz képest. A megoldás az, hogy eltoljuk a szakaszokat az origóba és a B A, C A pontokat hasonlítjuk össze véve a keresztszorzatukat. Szintén használhatjuk a keresztszorzatot annak eldöntésére, hogy egy AB irányított szakasz végpontjához csatlakozó BC szakasz jobbra vagy balra fordul. Azt kell megnéznünk, hogy a AC irányított szakasz az óramutató járásával megegyező vagy azzal ellentétes forgásirányban van a AB szakaszhoz képest. Tehát ha a (C A) (B A) keresztszorzat negatív, akkor B-ben balra fordulunk, ha pozitív jobbra, ha pedig 0, akkor a A, B,C pontok egy egyenesre esnek. Ennek eldontésére a FORGASIRANY(A,B,C) függvényt használjuk, amely 1, ha (C A) (B A) negatív, 1 ha a keresztszorzat pozitív és 0, ha a keresztszorzat 0. Szakaszok metszése Azt mondjuk a A,B szakasz átfog egy egyenest, ha A az egyenes egyik B pedig az egyenes másik oldalára esik. Két szakasz akkor és csak akkor metszi egymást ha az alábbi feltételek legalább egyike teljesül: Mindkét szakasz átfogja a másik egyenesét. Az egyik szakasz valamely végpontja illeszkedik a másik szakaszra. Felhasználjuk az alábbi eljárást, ami meghatározza, hogy az egy egyenesre eső A,B,C pontokra C eleme e az AB szakasznak. SZAKASZON(A,B,C) if min(a.x,b.x)<=c.x<=max(a.x,b.x) and min(a.y,b.y)<=c.y<=max(a.y,b.y) else return false 1
A következő eljárás megállapítja, hogy az AB és CD szakaszok metszik e egymást. SzakaszMetsz(A,B,C,D) e:=forgasirany(c,d,a) f:=forgasirany(c,d,b) g:=forgasirany(a,b,c) h:=forgasirany(a,b,d) if ef<0 and gh<0 if e=0 and SZAKASZON(C,D,A) if f=0 and SZAKASZON(C,D,B) if g=0 and SZAKASZON(A,B,C) if h=0 and SZAKASZON(A,B,D) return false Pont helyzete Adott a síkon egy zárt, nem-metsző poligon a csúcsainak p 1,..., p n órajárással ellentétes felsorolásával és adott egy q pont. Eldöntendő a q pontnak a poligonhoz viszonyított helyzete, azaz, hogy a belsejéhez tartozik-e, az oldalán van-e, avagy külső pont? Megoldás: Válasszunk egy olyan K pontot, amely biztosan nem tartozik a poligon belsejéhez és a poligon egyetlen csúcsa sem esik a Kq szakaszra, legfeljebb ha q megegyezik valamelyik csúccsal. Ha a Kq szakasz a poligon páratlan számú oldalát metszi, akkor q belső pont, egyébként külső. A K külső pont választása: Legyen K.y = max{p i.y p i.y < q.y,i = 1,...,n} és K.x = min{p i.x i = 1,...,n} 1. Ha a poligonnak nincs olyan csúcspontja, amelynek y-koordinátája kisebb, mint q.y, akkor q biztosan külső pont. A K pont ilyen választása esetén legfeljebb a q pont esik a poligon valamelyik oldalára, amikor is q nem belső pont lesz. Ezt az esetet külön kell ellenőrízni. Polárszög szerinti rendezés Legyen adott pontok egy P 1,...,P n halmaza. Sok esetben használható ezek polárszög szerinti rendezése, amely a következő eljárás. Válasszuk ki a legkisebb x-koordinátájú pontot, ha több ilyen van, akkor ezek közül válasszuk a legkisebb y- koordinátájút. Ezt nevezzük (bal-alsó) sarokpontnak és jelöljük Q-val. Húzzunk (fél) egyeneseket a Q sarokpontból minden ponthoz. Rendezzük az egyeneseket a Q ponton áthaladó, x-tengellyel párhuzamos egyenessel bezárt (előjeles) szög alapján. Jelölje ezt a szöget a Q,P egyenesre Φ(Q,P). Rendezzük a pontokat úgy, hogy a Q sarokpont legyen az első, és P előbb legyen mint R akkor és csak akkor, ha Φ(Q,P) < Φ(Q,R), vagy Φ(Q,P) = Φ(Q,R) és P közelebb van Q-hoz, azaz P.x < R.x, vagy Φ(Q,P) = Φ(Q,R) és P.x = R.x és P.y < R.y. 2
Két pont között a rendezési reláció megállapítható a tangensek összehasonlításával vagy a FORGASIRANY függvény felhasználásával. A rendezési reláció alapján pedig tetszőleges O(n log n) idejű algoritmust használhatunk a polárszög szerinti rendezés előállítására. Zárt poligon rajzolása Adott a síkon n darab pont, amelyek nem esnek egy egyenesre. A pontok (x,y) koordinátáikkal adottak, amelyek egész számok. A pontokat az 1,...,n számokkal azonosítjuk. Kössünk össze pontpárokat egyenes szakaszokkal úgy, hogy olyan zárt poligont kapjunk, amelyben nincs metsző szakaszpár. Megoldás: Ha a polárszög szerinti rendezés sorrendjében kötjük össze a pontokat, kivéve, hogy az utolsó egyenesen levő pontokat fordított sorrendben vesszük, akkor egy zárt, nem metsző poligont kapunk. Konvex burok Definíció: Egy egyszerű (nem metsző) poligon konvex, ha bármely két belső pontját összekötő szakasz minden pontja a poligon belsejében, vagy határán van. Definíció: Egy P = {p1,..., p n } ponthalmaz konvex burka az a legszűkebb Q konvex poligon, amely a ponthalmaz minden pontját tartalmazza. Feladat: Egy P ponthalmaz konvex burkának meghatározása. Megoldás: (Graham-féle pásztázás) Rendezzük a ponthalmaz pontjait polárszög szerint, majd minden egyenesen csak a sarokponttól legtávolabbi pontot hagyjuk meg, a többit töröljük. Legyen q 1,...,q m a kapott pontsorozat polárszög szerinti rendezésben. Mindaddig, amíg van három olyan egymást követő q i,q i+1 q i+2 pont, hogy q i+1,q i+2 jobbra fordul q i,q i+1 -hez képest, hagyjuk el a q i+1 pontot. Az alábbi algoritmusban feltesszük, hogy a PolarRendez algoritmus egy T (0-tól n-1-ig indexelt) tömböt ad, amely tartalmazza a pontokat polárszög szerinti rendezésben. KonvexBurok(P) T:=PolarRendez(P) m=1 for i=2 to n-1 while (m>0 and FORGASIRANY(T[m-1],T[m], T[i])<=0) m:=m-1 m:=m+1 Csere(P[m],P[i]) return m Az eljárásban mindig a tömb első m eleme tartalmazza az aktuális halmaz konvex burkának csúcsait. A for ciklus végigmegy a ponthalmaz pontain. Minden i-re a while ciklus törli azokat a pontokat, ahol a forgasirány nem megfelelő, majd az i elemet elhelyezi a konvex burok utolsó csúcsaként. Az algoritmus futási ideje O(nlogn), ha a polárszög szerinti rendezést olyan algoritmussal valósítjuk meg amelynek futási ideje O(nlogn). Metsző szakaszpárok létezésének vizsgálata A feladatban adott n darab szakasz S = {s 1,...,s n } (a szakaszok az s i.bal és s i. jobb végpontjaik által adottak) és meg kell határozni van a közöttük kettő olyan, amely metszi egymást. Seprő egyenes: Seprés során egy képzeletbeli seprő egyenest mozgatunk a geometriai elemek halmazán. Azt a dimenziót, amelyben a seprő egyenes halad, idődimenziónak szokás nevezni. Ennél a feladatnál a seprő egyenes az y-tengellyel párhuzamos egyenes, az idődimenzió az egyenest meghatározó x-koordináta lesz. 3
Egyszerűsítő feltételek: 1. Egyik bemeneti szakasz sem függőleges. 2. Nincs három olyan szakasz, amelyek egy pontban metszenék egymást. Szakaszok összehasonlítása: Legyen s 1 és s 2 szakasz és x R, akkor azt mondjuk, hogy a két szakasz összehasonlítható x -nél, ha mindkét szakasznak van olyan pontja, amelynek az x koordinátája x. Továbbá ez esetben s 1 > x s 2 ha s 1 -nek az x x-koordinátájú pontjának y koordinátája nagyobb. (Azaz az x -ben húzott seprő egyenessel vett metszete magasabban van.) Ez a reláció minden x esetén az összehasonlítható pontok egy lineáris rendezését adja. Továbbá ha két szakasz metszi egymást, akkor a metszést megelőzően a rendezésben egymást követik, így elég a rendezésben egymás melletti szakaszokat vizsgálni van a metszéspontjuk. Fontos megjegyezni, hogy ha két szakasz nem metszi egymást, akkor a szakaszok egymáshoz viszonyított helyzete nem változik x változtatásával. 1. Esetpontok jegyzéke: azon időpontok (rendezett) sorozata, amely időpontokban a seprő egyenes megáll. (Ezen pontok {s.bal.x, s. jobb.x : s S} 2. A seprő egyenes állapotleírása: az egyenes által metszett szakaszok rendezett halmaza. Az esetpontok halmazát rendezzük, ha több pontnak ugyanaz az x koordinátája, akkor a bal végpontokat vesszük előszőr figyelembe (növekvő y koordináta szerint), majd a jobb végpontokat (szintén növekvő y koordináta szerint). A seprő egyenes által metszett szakaszok nyilvántartására egy olyan T adattípusra van szükség, amely hatékonyan megoldja a Bovit(T,s), Torol(T,s), Eloz(T,s), Kovet(T,s) műveleteket, ilyen a rendezett halmaz absztrakt adattípus. (Piros fekete fával való megvalósítás mellett a műveletek mindegyike O(logn) időben végrehajtható.) Az alábbi algoritmusban feltesszük, hogy az ESEMENY algoritmus az eseménypontokat a fentiekben leírtak alapján rendezi. MetszoPar(S) Letesit(T:RHalmaz) R:=ESEMENY(S) minden p-re az R beli sorrendben if p=s.bal then Bovit(T,s) If SzakaszMetsz(Kovet(T,s),s) or SzakaszMetsz(Eloz(T,s),s) then return True if p=s.jobb then If SzakaszMetsz(Kovet(T,s),Eloz(T,s)) then return True Torol(T,s) Az algoritmus futási ideje piros fekete fával történő megvalósítás mellett O(nlogn). Egymáshoz legközelebbi pontpár megkeresése A két pont távolsága az Euklideszi távolság, azaz tav(p,q) = (p.x q.x) 2 + (p.y q.y) 2. A feladat P = {p 1,..., p n } ponthalmazban megtalálni azt a két p i, p j pontot, amelyek távolsága minimális. Kézenfekvő megoldás a NAIV algoritmus, ami megvizsgál minden pontpárt és veszi a minimális távolságot, ennek az algoritmusnak Θ(n 2 ) a futási ideje. Az alábbiakban egy gyorsabb oszd meg és uralkodj elvű algoritmust adunk meg. Legyen S a pontok halmaza, X a pontok x-koordináta szerint rendezett sorozata, Y pedig pontok y-koordináta szerint rendezett sorozata. (A rendezések megoldhatóak O(nlogn) időben.) Az elvi algoritmus 4
TAVKERES(P,X,Y) if P 3 then return NAIV(P) Legyen P L, P P /2 legkisebb x koordinátájú eleme. Legyenek X L,Y L a P L beli pontok rendezett halmazai. Legyen P R P többi eleme Legyenek X R,Y R a P R beli pontok rendezett halmazai. Legyen x 0 P L -t és P R szeparáló x koordináta (d L,a L,b L ) := TAV KERES(P L,X L,Y L ) (d R,a R,b R ) := TAV KERES(P R,X R,Y R ) d := min(d L,d R ) Y d := azon P-beli pontok y koordináta szerint rendezett halmaza, amelyek x-koordinátájára x 0 x d Ha van Y d -ben d-nél közelebbi pár, akkor azt adjuk vissza, egyébként d-t a megfelelő pontpárral. Igazolható, hogy a középső sávban (Y d ) elég minden p pontra csak p-t követő 7 pontra nézni a távolságot, hogy találjuk d-nél közelebbi pontpárt, ha létezik ilyen. Ezt a tényt használva az algoritmus utolsó lépésében, azt kapjuk, hogy a legrosszabb futási időre fennáll T (n) = 2T (n/2) + O(n) összefüggés, így T (n) = O(n log n). Egymástól legtávolabbi pontpár megkeresése A feladat P = {p 1,..., p n } ponthalmazban megtalálni azt a két p i, p j pontot, amelyek távolsága minimális. Kézenfekvő megoldás a NAIV algoritmus, ami megvizsgál minden pontpárt és veszi a minimális távolságot, ennek az algoritmusnak Θ(n 2 ) a futási ideje. Az alábbiakban egy gyorsabb, a konvex burkon alapuló algoritmust alapötletét adjuk meg. Lemma A legtávolabbi pontpár P konvex burkának két pontja lesz. Definíció A P ponthalmaz átellenes pontpárja olyan p i és p j pontpár, amelyre van olyan p i -n és p j -n átmenő egyenes, amelyek párhuzamosak és a P ponthalmaz minden pontja a két egyenes közé esik. Lemma A legtávolabbi pontpárban szereplő pontok átellenesek. Átellenes pontpárok meghatározása görgetéssel Legyen P = {p 1,..., p m } a konvex poligon csúcspontjainak órajárással ellentétes felsorolása. Legyen p i a konvex poligon legkisebb y-koordinátájú pontja, ha kettő ilyen van, akkor ezek közöl válasszuk a legnagyobb x-koordinátájút. Legyen továbbá p j pedig a legnagyobb y-koordinátájú pontja, ha kettő ilyen van, akkor ezek közül válasszuk a legkisebb x-koordinátájút. Ekkor p i és p j nyilvánvalóan átellenes pontjai a poligonnak. Az többi átellenes pontpár lineáris időben meghatározható görgetéssel. Forgassuk el balra az aktuális átellenes p k és p r pontokon átmenő párhuzamos egyeneseket amíg valamelyik a p k p k+1 vagy a p r, p r+1 oldalra nem ér (a +1 modulo m értendő). Ha előbb érjük el a p k p k+1 oldalt, akkor k := k + 1, egyébként r := r + 1. Folytassuk ezt mindaddig, amíg vissza nem érünk a kezdetben választott két átellenes ponthoz. Annak eldöntése, hogy melyik oldalt érjük el hamarabb a forgatással a FORGASIRANY(p r+1, p i+1 p k + p r+1, p r ) függvény kiszámításával meghatározható. Az algoritmus futási ideje O(nlogn). Szorgalmi Adott n pont a síkon a koordinátáik által megadva. Adjunk egy lineáris idejű algoritmust, amely eldönti van -e három olyan egyenes, amely a pontok mindegyikét tartalmazza. Beküldés: cimreh@inf.u-szeged.hu, Pszeudókód + futási idő igazolása első négy megoldó 8-8 pont 5
a második négy megoldó 4-4 pont A szerzett plusszpontok a vizsga minimumkövetelményébe nem számítanak bele. 6