Chapter 30 first version
This commit is contained in:
parent
0a9b4770ef
commit
45279464a3
307
luku30.tex
307
luku30.tex
|
@ -1,33 +1,31 @@
|
||||||
\chapter{Sweep line}
|
\chapter{Sweep line algorithms}
|
||||||
|
|
||||||
\index{pyyhkxisyviiva@pyyhkäisyviiva}
|
\index{sweep line}
|
||||||
|
|
||||||
\key{Pyyhkäisyviiva} on tason halki kulkeva viiva,
|
Many geometric problems can be solved using
|
||||||
jonka avulla voi ratkaista useita geometrisia tehtäviä.
|
\key{sweep line} algorithms.
|
||||||
Ideana on esittää tehtävä joukkona tapahtumia,
|
The idea in such algorithms is to represent
|
||||||
jotka vastaavat tason pisteitä.
|
the problem as a set of events that correspond
|
||||||
Kun pyyhkäisyviiva törmää pisteeseen,
|
to points in the plane.
|
||||||
tapahtuma käsitellään ja tehtävän ratkaisu edistyy.
|
The events are processed in a sorted order
|
||||||
|
according to their x or y coordinate.
|
||||||
|
|
||||||
Tarkastellaan esimerkkinä tekniikan
|
As an example, let us consider a problem
|
||||||
käyttämisestä tehtävää,
|
where there is a company that has $n$ employees,
|
||||||
jossa yrityksessä on töissä $n$ henkilöä
|
and we know for each employee arrival and
|
||||||
ja jokaisesta henkilöstä tiedetään,
|
leaving times on a certain day.
|
||||||
milloin hän tuli töihin ja lähti töistä
|
Our task is to calculate the maximum number of
|
||||||
tiettynä päivänä.
|
employees that were in the office at the same time.
|
||||||
Tehtävänä on laskea,
|
|
||||||
mikä on suurin määrä henkilöitä,
|
|
||||||
jotka olivat samaan aikaan töissä.
|
|
||||||
|
|
||||||
Tehtävän voi ratkaista mallintamalla tilanteen
|
The problem can be solved by modelling the situation
|
||||||
niin, että jokaista henkilöä vastaa kaksi tapahtumaa:
|
so that each employee is assigned two events that
|
||||||
tuloaika töihin ja lähtöaika töistä.
|
corresponds to the arrival and leaving times.
|
||||||
Pyyhkäisyviiva käy läpi tapahtumat aikajärjestyksessä
|
After sorting the events, we can go trough them
|
||||||
ja pitää kirjaa, montako henkilöä oli töissä milloinkin.
|
and keep track of the number of people in the office.
|
||||||
Esimerkiksi tilannetta
|
For example, the table
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tabular}{ccc}
|
\begin{tabular}{ccc}
|
||||||
henkilö & tuloaika & lähtöaika \\
|
person & arrival time & leaving time \\
|
||||||
\hline
|
\hline
|
||||||
Uolevi & 10 & 15 \\
|
Uolevi & 10 & 15 \\
|
||||||
Maija & 6 & 12 \\
|
Maija & 6 & 12 \\
|
||||||
|
@ -35,7 +33,7 @@ Kaaleppi & 14 & 16 \\
|
||||||
Liisa & 5 & 13 \\
|
Liisa & 5 & 13 \\
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
\end{center}
|
\end{center}
|
||||||
vastaavat seuraavat tapahtumat:
|
generates the following events:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.6]
|
\begin{tikzpicture}[scale=0.6]
|
||||||
\draw (0,0) rectangle (17,-6.5);
|
\draw (0,0) rectangle (17,-6.5);
|
||||||
|
@ -59,15 +57,16 @@ vastaavat seuraavat tapahtumat:
|
||||||
\node at (2,-5.5) {Liisa};
|
\node at (2,-5.5) {Liisa};
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Pyyhkäisyviiva käy läpi tapahtumat vasemmalta oikealle
|
We go through the events from left to right
|
||||||
ja pitää yllä laskuria.
|
and maintain a counter.
|
||||||
Aina kun henkilö tulee töihin, laskurin arvo
|
Always when a person arrives, we increase
|
||||||
kasvaa yhdellä, ja kun henkilö lähtee töistä,
|
the value of the counter by one,
|
||||||
laskurin arvo vähenee yhdellä.
|
and when a person leaves,
|
||||||
Tehtävän ratkaisu on suurin laskuri arvo
|
we decrease the value by one.
|
||||||
pyyhkäisyviivan kulun aikana.
|
The answer for the problem is the maximum
|
||||||
|
value of the counter during the algorithm.
|
||||||
|
|
||||||
Pyyhkäisyviiva kulkee seuraavasti tason halki:
|
In the example, the events are processed as follows:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.6]
|
\begin{tikzpicture}[scale=0.6]
|
||||||
\path[draw,thick,->] (0.5,0.5) -- (16.5,0.5);
|
\path[draw,thick,->] (0.5,0.5) -- (16.5,0.5);
|
||||||
|
@ -119,26 +118,24 @@ Pyyhkäisyviiva kulkee seuraavasti tason halki:
|
||||||
\node at (13,-8) {$1$};
|
\node at (13,-8) {$1$};
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Kuvan alareunan merkinnät $+$ ja $-$
|
The symbols $+$ and $-$ indicate whether the
|
||||||
tarkoittavat, että laskurin arvo kasvaa
|
value of the counter increases of decreases,
|
||||||
ja vähenee yhdellä.
|
and the value of the counter is shown below.
|
||||||
Niiden alapuolella on laskurin uusi arvo.
|
The maximum value of the counter is 3
|
||||||
Laskurin suurin arvo 3 on voimassa
|
between Uolevi's arrival and Maija's leaving.
|
||||||
Uolevi tulohetken ja Maijan lähtöhetken välillä.
|
|
||||||
|
|
||||||
Ratkaisun aikavaativuus on $O(n \log n)$,
|
The running time of the solution is $O(n \log n)$,
|
||||||
koska tapahtumien järjestäminen vie aikaa $O(n \log n)$
|
because sorting the events takes $O(n \log n)$ time
|
||||||
ja pyyhkäisyviivan läpikäynti vie aikaa $O(n)$.
|
and the rest of the algorithm takes $O(n)$ time.
|
||||||
|
|
||||||
\section{Janojen leikkauspisteet}
|
\section{Intersection points}
|
||||||
|
|
||||||
\index{leikkauspiste@leikkauspiste}
|
\index{intersection point}
|
||||||
|
|
||||||
Annettuna on $n$ janaa, joista jokainen
|
Given a set of $n$ line segments, each of them being either
|
||||||
on vaaka- tai pystysuuntainen.
|
horizontal or vertical, the problem is to efficiently
|
||||||
Tehtävänä on laskea tehokkaasti, monessako pisteessä
|
calculate the total number of intersection points.
|
||||||
kaksi janaa leikkaavat toisensa.
|
For example, when the line segments are
|
||||||
Esimerkiksi tilanteessa
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.5]
|
\begin{tikzpicture}[scale=0.5]
|
||||||
\path[draw,thick,-] (0,2) -- (5,2);
|
\path[draw,thick,-] (0,2) -- (5,2);
|
||||||
|
@ -148,7 +145,7 @@ Esimerkiksi tilanteessa
|
||||||
\path[draw,thick,-] (8,2) -- (8,5);
|
\path[draw,thick,-] (8,2) -- (8,5);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
leikkauspisteitä on kolme:
|
there are three intersection points:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.5]
|
\begin{tikzpicture}[scale=0.5]
|
||||||
\path[draw,thick,-] (0,2) -- (5,2);
|
\path[draw,thick,-] (0,2) -- (5,2);
|
||||||
|
@ -164,21 +161,20 @@ leikkauspisteitä on kolme:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
|
It is easy to solve the problem in $O(n^2)$ time,
|
||||||
|
because we can go through all possible pairs of segments
|
||||||
|
and check if they intersect.
|
||||||
|
However, we can solve the problem more efficiently
|
||||||
|
in $O(n \log n)$ time using a sweep line algorithm.
|
||||||
|
|
||||||
Tehtävä on helppoa ratkaista ajassa $O(n^2)$,
|
The idea is to generate two types of events:
|
||||||
koska riittää käydä läpi kaikki mahdolliset janaparit
|
|
||||||
ja tarkistaa, moniko leikkaa toisiaan.
|
|
||||||
Seuraavaksi ratkaisemme tehtävän
|
|
||||||
ajassa $O(n \log n)$ pyyhkäisyviivan avulla.
|
|
||||||
|
|
||||||
Ideana on luoda janoista kolmenlaisia tapahtumia:
|
|
||||||
\begin{enumerate}[noitemsep]
|
\begin{enumerate}[noitemsep]
|
||||||
\item[(1)] vaakajana alkaa
|
\item[(1)] horizontal segment begins
|
||||||
\item[(2)] vaakajana päättyy
|
\item[(2)] horizontal segment ends
|
||||||
\item[(3)] pystyjana
|
\item[(3)] vertical segment
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
Esimerkkitilannetta vastaava pistejoukko on seuraava:
|
The following events correspond to the example:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.6]
|
\begin{tikzpicture}[scale=0.6]
|
||||||
\path[draw,dashed] (0,2) -- (5,2);
|
\path[draw,dashed] (0,2) -- (5,2);
|
||||||
|
@ -199,37 +195,35 @@ Esimerkkitilannetta vastaava pistejoukko on seuraava:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Algoritmi käy läpi pisteet vasemmalta oikealle
|
We go through the events from left to right
|
||||||
ja pitää yllä tietorakennetta y-koordinaateista,
|
and use a data structure that maintains a set of
|
||||||
joissa on tällä hetkellä aktiivinen vaakajana.
|
y coordinates where there is an active horizontal segment.
|
||||||
Tapahtuman 1 kohdalla vaakajanan y-koordinaatti
|
At event 1, we add the y coordinate of the segment
|
||||||
lisätään joukkoon ja tapahtuman 2 kohdalla
|
to the set, and at event 2, we remove the
|
||||||
vaakajanan y-koordinaatti poistetaan joukosta.
|
y coordinate from the set.
|
||||||
|
|
||||||
Algoritmi laskee janojen leikkauspisteet
|
Intersection points are calculated at event 3.
|
||||||
tapahtumien 3 kohdalla.
|
When there is a vertical segment between points
|
||||||
Kun pystyjana kulkee y-koordinaattien
|
$y_1$ and $y_2$, we count the number of active
|
||||||
$y_1 \ldots y_2$ välillä,
|
horizontal segments whose y coordinate is between
|
||||||
algoritmi laskee tietorakenteesta,
|
$y_1$ and $y_2$, and at this number to the total
|
||||||
monessako vaakajanassa on y-koordinaatti
|
number of intersection points.
|
||||||
välillä $y_1 \ldots y_2$ ja kasvattaa
|
|
||||||
leikkauspisteiden määrää tällä arvolla.
|
|
||||||
|
|
||||||
Sopiva tietorakenne vaakajanojen y-koordinaattien
|
An appropriate data structure for storing
|
||||||
tallentamiseen on bi\-nää\-ri-indeksipuu tai segmenttipuu,
|
y coordinates of horizontal segments is either
|
||||||
johon on tarvittaessa yhdistetty indeksien pakkaus.
|
a binary-indexed tree or a segment tree,
|
||||||
Tällöin jokaisen pisteen käsittely
|
possibly with index compression.
|
||||||
vie aikaa $O(\log n)$, joten algoritmin
|
Using such structures, processing each event
|
||||||
kokonaisaikavaativuus on $O(n \log n)$.
|
takes $O(\log n)$ time, so the total running
|
||||||
|
time of the algorithm is $O(n \log n)$.
|
||||||
|
|
||||||
\section{Lähin pistepari}
|
\section{Nearest points}
|
||||||
|
|
||||||
\index{lzhin pistepari@lähin pistepari}
|
\index{nearest points}
|
||||||
|
|
||||||
Seuraava tehtävämme on etsiä $n$ pisteen
|
Given a set of $n$ points, our next problem is
|
||||||
joukosta kaksi pistettä, jotka ovat
|
to find two points whose distance is minimum.
|
||||||
mahdollisimman lähellä toisiaan.
|
For example, if the points are
|
||||||
Esimerkiksi tilanteessa
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0)--(12,0)--(12,4)--(0,4)--(0,0);
|
\draw (0,0)--(12,0)--(12,4)--(0,4)--(0,0);
|
||||||
|
@ -251,7 +245,7 @@ Esimerkiksi tilanteessa
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
\begin{samepage}
|
\begin{samepage}
|
||||||
lähin pistepari on seuraava:
|
we should find the following points:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0)--(12,0)--(12,4)--(0,4)--(0,0);
|
\draw (0,0)--(12,0)--(12,4)--(0,4)--(0,0);
|
||||||
|
@ -274,32 +268,30 @@ lähin pistepari on seuraava:
|
||||||
\end{center}
|
\end{center}
|
||||||
\end{samepage}
|
\end{samepage}
|
||||||
|
|
||||||
Tämäkin tehtävä ratkeaa
|
This problem can be also solved in $O(n \log n)$ time
|
||||||
$O(n \log n)$-ajassa pyyhkäisyviivan avulla.
|
using a sweep line algorithm.
|
||||||
Algoritmi käy pisteet läpi vasemmalta oikealle
|
We go through the points from left to right
|
||||||
ja pitää yllä arvoa $d$,
|
and maintain a value $d$: the minimum distance
|
||||||
joka on pienin kahden
|
between two points so far.
|
||||||
pisteen etäisyys.
|
At each point, we find the nearest point to the left.
|
||||||
Kunkin pisteen kohdalla algoritmi
|
If the distance is less than $d$, it is the
|
||||||
etsii lähimmän toisen pisteen vasemmalta.
|
new minimum distance and we update
|
||||||
Jos etäisyys tähän pisteeseen on alle $d$,
|
the value of $d$.
|
||||||
tämä on uusi pienin kahden pisteen etäisyys
|
|
||||||
ja algoritmi päivittää $d$:n arvon.
|
|
||||||
|
|
||||||
Jos käsiteltävä piste on $(x,y)$
|
If the current point is $(x,y)$
|
||||||
ja jokin vasemmalla oleva piste on
|
and there is a point to the left
|
||||||
alle $d$:n etäisyydellä,
|
within a distance of less than $d$,
|
||||||
sen x-koordinaatin
|
the x coordinate of such a point must
|
||||||
tulee olla välillä $[x-d,x]$
|
be between $[x-d,x]$ and the y coordinate
|
||||||
ja y-koordinaatin tulee olla välillä $[y-d,y+d]$.
|
must be between $[y-d,y+d]$.
|
||||||
Algoritmin riittää siis tarkistaa
|
Thus, it suffices to only consider points
|
||||||
ainoastaan pisteet, jotka osuvat tälle välille,
|
that are located in those ranges,
|
||||||
mikä tehostaa hakua merkittävästi.
|
which makes the algorithm efficient.
|
||||||
|
|
||||||
Esimerkiksi seuraavassa kuvassa
|
For example, in the following picture the
|
||||||
katkoviiva-alue sisältää pisteet,
|
region marked with dashed lines contains
|
||||||
jotka voivat olla alle $d$:n etäisyydellä
|
the points that can be within a distance of $d$
|
||||||
tummennetusta pisteestä.
|
from the active point:
|
||||||
\\
|
\\
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
|
@ -332,34 +324,31 @@ tummennetusta pisteestä.
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Algoritmin tehokkuus perustuu siihen,
|
The efficiency of the algorithm is based on the fact
|
||||||
että $d$:n rajoittamalla alueella
|
that the region limited by $d$ always contains
|
||||||
on aina vain $O(1)$ pistettä.
|
only $O(1)$ points.
|
||||||
Nämä pisteet pystyy käymään läpi
|
We can go through those points in $O(\log n)$ time
|
||||||
$O(\log n)$-aikaisesti
|
by maintaining a set of points whose x coordinate
|
||||||
pitämällä algoritmin aikana yllä joukkoa pisteistä,
|
is between $[x-d,x]$ and that are sorted according
|
||||||
joiden x-koordinaatti on välillä $[x-d,x]$
|
to the y coordinate.
|
||||||
ja jotka on järjestetty y-koordinaatin mukaan.
|
|
||||||
|
|
||||||
Algoritmin aikavaativuus on $O(n \log n)$,
|
The time complexity of the algorithm is $O(n \log n)$,
|
||||||
koska se käy läpi $n$ pistettä
|
because it goes through $n$ points and
|
||||||
ja etsii jokaiselle lähimmän
|
finds for each point the nearest point to the left
|
||||||
edeltävän pisteen ajassa $O(\log n)$.
|
in $O(\log n)$ time.
|
||||||
|
|
||||||
\section{Konveksi peite}
|
\section{Convex hull}
|
||||||
|
|
||||||
\key{Konveksi peite}
|
The \key{convex hull} is the smallest convex polygon
|
||||||
on pienin konveksi monikulmio,
|
that contains all points in a given set.
|
||||||
joka ympäröi kaikki pistejoukon pisteet.
|
Convexity means that a line segment between
|
||||||
Konveksius tarkoittaa,
|
any two vertices of the polygon is completely
|
||||||
että minkä tahansa kahden kärkipisteen välinen jana
|
inside the polygon.
|
||||||
kulkee monikulmion sisällä.
|
A good intuitive definition is that we surround
|
||||||
Hyvä mielikuva asiasta on,
|
the points using a tight rope.
|
||||||
että pistejoukko ympäröidään tiukasti
|
|
||||||
viritetyllä narulla.
|
|
||||||
|
|
||||||
\begin{samepage}
|
\begin{samepage}
|
||||||
Esimerkiksi pistejoukon
|
For example, for the points
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0) circle [radius=0.1];
|
\draw (0,0) circle [radius=0.1];
|
||||||
|
@ -379,7 +368,7 @@ Esimerkiksi pistejoukon
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
\end{samepage}
|
\end{samepage}
|
||||||
konveksi peite on seuraava:
|
the convex hull is as follows:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0)--(4,-1)--(7,1)--(6,3)--(2,4)--(0,2)--(0,0);
|
\draw (0,0)--(4,-1)--(7,1)--(6,3)--(2,4)--(0,2)--(0,0);
|
||||||
|
@ -401,34 +390,30 @@ konveksi peite on seuraava:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
\index{Andrew'n algoritmi}
|
\index{Andrew's algorithm}
|
||||||
|
|
||||||
Tehokas ja helposti toteutettava menetelmä
|
A good way to construct the convex hull
|
||||||
konveksin peitteen muodostamiseen
|
is \key{Andrew's algorithm}
|
||||||
on \key{Andrew'n algoritmi},
|
that works in $O(n \log n)$ time.
|
||||||
jonka aikavaativuus on $O(n \log n)$.
|
The algorithm constructs the convex hull
|
||||||
Algoritmi muodostaa konveksin peitteen kahdessa
|
in two steps:
|
||||||
osassa: ensin peitteen yläosan ja sitten peitteen alaosan.
|
first the upper hull and then the lower hull.
|
||||||
Kummankin osan muodostaminen tapahtuu samalla tavalla,
|
Both steps are similar, so we can focus on
|
||||||
minkä vuoksi voimme keskittyä yläosan muodostamiseen.
|
constructing the upper hull.
|
||||||
|
|
||||||
Algoritmi järjestää ensin pisteet ensisijaisesti x-koordinaatin
|
We sort the points primarily according to
|
||||||
ja toissijaisesti y-koordinaatin mukaan.
|
x coordinates and secondarily according to y coordinates.
|
||||||
Tämän jälkeen se käy pisteet läpi järjestyksessä
|
After this, we go through the points and always
|
||||||
ja lisää aina uuden pisteen osaksi peitettä.
|
add the new point to the hull.
|
||||||
Aina pisteen lisäämisen jälkeen algoritmi tarkastaa
|
After adding a point we check using cross products
|
||||||
ristitulon avulla,
|
whether the tree last point in the hull turn left.
|
||||||
muodostavatko kolme viimeistä pistettä peitteessä
|
If this holds, we remove the middle point from the hull.
|
||||||
vasemmalle kääntyvän osan.
|
After this we keep checking again the three last points
|
||||||
Jos näin on,
|
and removing points, until the three last points
|
||||||
algoritmi poistaa näistä keskimmäisen pisteen.
|
don't turn left.
|
||||||
Tämän jälkeen algoritmi tarkastaa uudestaan
|
|
||||||
kolme viimeistä pistettä ja poistaa taas tarvittaessa
|
|
||||||
keskimmäisen pisteen.
|
|
||||||
Sama jatkuu, kunnes kolme viimeistä pistettä
|
|
||||||
eivät muodosta vasemmalle kääntyvää osaa.
|
|
||||||
|
|
||||||
Seuraava kuvasarja esittää Andrew'n algoritmin toimintaa:
|
The following pictures show how
|
||||||
|
Andrew's algorithm works:
|
||||||
\\
|
\\
|
||||||
\begin{tabular}{ccccccc}
|
\begin{tabular}{ccccccc}
|
||||||
\\
|
\\
|
||||||
|
|
Loading…
Reference in New Issue