Sunteți pe pagina 1din 76

Copie autorizata pentru .

campion

Sergiu CORLAT

Algoritmi i probleme
de geometrie computaional

Copie autorizata pentru .campion

Aprobat la edina Senatului Universitii de Stat din


Tiraspol din 26 ianuarie 2009.
Toate drepturile asupra acestei ediii aparin autorului.
Reproducerea integral sau parial a textului sau a
ilustraiilor din aceast ediie este permis doar cu acordul scris al autorului.
Autor:

Sergiu Corlat, lector superior, UST

Recenzeni:



Andrei Braicov,
doctor, confereniar universitar, UST
Emanuela Cerchez,
profesor gradul I, Liceul de Informatic
Grigore Moisil, Iai

Redactor:

Tatiana Rusu

Coperta:

Valentina Stratu

Sergiu Corlat, 2009


Editura Prut Internaional, 2009
Editura Prut Internaional, str. George Enescu, nr. 6,
bl.1, Chiinu MD 2064
Tel.: 75 18 74, 74 93 18; fax: 50 87 20; e-mail: prut@mtc.md
CZU 519.6+514 C15
ISBN 978-9975-69-377-6

Copie autorizata pentru .campion

Cuprins
Introducere

1. Transformri de coordonate 7
1.1. Deplasri i rotaii
7
1.2. Coordonate polare 9
1.3. Implementri
10

12

2.1. Intersecia dreptelor


2.2. Intersecia dreptei cu un segment
2.3. Intersecia segmentelor

12
14
16

3. nfurtoarea convex

17

3.1. Algoritmul elementar


3.2. Algoritmul Graham

17
20

26

4.1. Un algoritm greedy pentru


mulimi de puncte
4.2. Triangularizarea poligoanelor convexe
4.3. Triangularizarea poligoanelor simple

26
28
29

31

5.1. Cea mai apropiat pereche de puncte


5.2. Apartenena punctului la un domeniu
5.3. Poligonul i diagrama Voronoi
5.4. Nuclee

31
35
39
44

2. Intersecii

4. Triangularizri

5. Apropiere i apartenen

Copie autorizata pentru .campion

6. Probleme geometrice de concurs

48

6.1. Robot
6.2. Robot II
6.3. Piatra
6.4. Carcasa
6.5. Turnuri
6.6. Atac
6.7. Evadare
6.8. Arcai
6.9. Cetate
6.10. Druizi

48
50
52
54
56
57
61
62
68
69

Notaii
Bibliografie

75
76

Introducere

Copie autorizata pentru .campion

Geometria computaional constituie una din ramurile


importante ale matematicii aplicate moderne. Pornind
de la cercetarea unor elemente geometrice simple (punct,
segment, dreapt), se ajunge la o modelare complex a
figurilor geometrice n plan i a corpurilor n spaiul tridimensional.
Algoritmii geometriei computaionale stau la baza tuturor aplicaiilor de proiectare i modelare grafic (aplicaii
CAD, procesoare de grafic vectorial, aplicaii de modelare
3D). Fr ei ar fi imposibil proiectarea construciilor arhitecturale moderne, realizarea proiectelor GPS, apariia
majoritii absolute a produselor cinematografice de succes din ultimii ani. Enumerarea domeniilor de aplicare
poate fi continuat la nesfrit.
Domeniul vast de aplicare i multitudinea fenomenelor i situaiilor reale, descrise n termenii geometriei
computaionale, au impus apariia unor probleme geometrice n cadrul concursurilor de programare de cele mai
diferite nivele.
Prezenta lucrare este conceput ca un curs de iniiere n
algoritmii de geometrie computaional pentru studenii
facultilor de profil, pentru profesorii de informatic,
precum i pentru elevii claselor liceale, participani la
concursurile naionale i internaionale de programare.
Un alt scop este de a-i forma cititorului abiliti de
analiz i proiectare a algoritmilor. n acest sens, algoritmii i soluiile problemelor sunt nsoite de descrieri
ale structurilor de date, fragmente de cod, de calcule ale
complexitii.

Copie autorizata pentru .campion

Cu toate c aparatul matematic necesar pentru rezolvarea problemelor de geometrie computaional este
relativ simplu, implementarea acestuia este nsoit de
necesitatea cercetrii unui numr considerabil de cazuri
speciale. Acesta este un motiv pentru care problemele de
geometrie computaional se consider printre cele mai
dificile, n special n condiii de concurs.
Cercetarea i optimizarea soluiilor propuse pentru
unele din problemele prezente n lucrare i vor permite
cititorului s capete o experien necesar la compartimentul rezolvare de probleme i, nu n ultimul rnd, la
generarea testelor pentru verificarea soluiilor.
La baza lucrrii se afl o serie de articole publicate
pe parcursul ultimilor ani n revista de matematic i
informatic Delta, materiale i probleme elaborate n
cadrul colilor de var la informatic (ediiile anilor
2001, 2002), precum i probleme propuse la concursul de pregtire continu la informatic .campion
(campion.edu.ro).
in s aduc sincere mulumiri tuturor celor care au
contribuit la apariia acestei cri, n special colectivului
Catedrei de Informatic i Tehnologii Informaionale a
Universitii de Stat din Tiraspol.
Ianuarie 2009

Sergiu Corlat

Copie autorizata pentru .campion

1. Transformri de coordonate
1.1. Deplasri i rotaii
Rezolvarea oricrei probleme de geometrie computa
ional ncepe (dac e necesar) cu deplasarea coordonatelor elementelor cercetate (de cele mai dese ori, ale punctelor) ntr-un domeniu potrivit al sistemului de coordonate
(de obicei, n cadranul unu). n unele cazuri, deplasarea
poate fi nsoit i de rotaia sistemului de coordonate.
Fie ntr-un sistem cartezian de coordonate un punct p
de coordonate (x, y). Deplasarea de coordonate de-a lungul
axei Ox cu o valoare dat a implic o modificare a coordonatelor punctului conform formulelor:

x = x + a ,

y = y.
n cazul deplasrii de-a lungul
axei Oy cu valoarea b, transformarea
de coordonate va fi dat de sistemul:

x = x,

y = y + b.

Modificarea combinat a coordonatelor cu a dup axa Ox i b dup


Oy va fi dat de sistemul:

Fig. 1.1. Rotaia punctului


cu un unghi

x = x + a ,

y = y + b.
Urmtorul tip de transformare este rotaia cu un unghi

a punctului (punctelor) fa de originea sistemului de

coordonate (fig. 1.1).

Copie autorizata pentru .campion

n unele cazuri,
operaia poate fi re
alizat invers: prin
rotaia originii siste
mului de coordonate
fa de un punct (sau
sistem de puncte) dat.
Atunci exist patru
numere a, b, c, d, care
permit de a trece univoc coordonatele ( x, y )
n ( x, y) , utiliznd
sistemul de ecuaii:

Fig.1.2. Determinarea cuadruplului a, b, c, d folosind punctele (1, 0) i (0, 1)

x = ax + by,
(1.1)

y = cx + dy.
Pentru a determina acest cuadruplu de numere, pot fi
folosite punctele (1, 0) i (0, 1).
Se observ c la rotaia cu un unghi punctul de coordonate (1, 0) trece n punctul (cos ,sin ) , iar punctul de
coordonate (0, 1) n ( sin , cos ) (fig. 1.2).
Dup substituia acestor valori, n calitate de coeficieni
ai sistemului (1.1) se obine:

x = a
a = cos ,

y = c
c = sin .
Analog:

x = b
b = sin ,

y = d
d = cos .

Copie autorizata pentru .campion

Astfel, sistemul de ecuaii pentru rotaia cu un unghi

a unui punct arbitrar n jurul originii sistemului de co-

ordonate ia forma:

x = x cos y sin ,

y = x sin + y cos .
n cazul n care rotaia cu unghiul a punctului de
coordonate ( x, y ) este efectuat fa de punctul de coordonate ( x0 , y0 ) , diferit de originea sistemului de coordonate,
nti se transfer originea sistemului de coordonate n
centrul de rotaie, apoi se efectueaz rotaia n jurul noii
origini a sistemului de coordonate:

x x0 = ( x x0 ) cos ( y y0 ) sin

y y0 = ( x x0 ) sin + ( y y0 ) cos

sau

x = x0 + ( x x0 ) cos ( y y0 ) sin

y = y0 + ( x x0 ) sin + ( y y0 ) cos

1.2. Coordonate polare


Problemele n care apare necesitatea parcurgerii unei
mulimi de puncte pi , i = 1, N de
coordonate (xi , yi) dup
unghiurile formate de vectorii Opi cu axa Ox se rezolv
mai simplu n coordonate
polare, unde fiecare punct p
este determinat de perechea
(r , ) , unde r este distana
de la punct pn la originea
sistemului de coordonate, iar
format de vecto unghiul

Fig. 1.3. Coordonatele polare ale


rul Op cu axa Ox (fig. 1.3).
punctului de coordonate carteziene
(x, y)

Copie autorizata pentru .campion

Trecerea de la coordonatele carteziene (x, y) la cele polare este determinat de urmtoarele formule [1, p. 77]:

r= x +y ,

arctan y

+ arctan y
=

y>0
y<0
x = 0, y > 0
x = 0, y < 0

1.3. Implementri
n problemele de geometrie computaional pot aprea
diferite modele de transformare a coordonatelor: deplasri
dup o ax, deplasri combinate (dup ambele axe), rotaii
fa de un punct, deplasri nsoite de rotaii. Toate aceste
transformri presupun recalcularea coordonatelor unui
punct sau ale unui sistem de puncte.
Pentru rezolvarea eficient a problemelor de geometrie
este foarte important de a alege corect structurile de date.
Pentru implementarea transformrilor de coordonate este
necesar descrierea unei singure structuri punctul:
type point=record
x,y : real;
end;

Orice obiect geometric determinat de un sistem de


puncte poate fi descris cu ajutorul unui tablou unidimensional sau printr-o list alocat dinamic, cu elemente de
tip point.
10

Copie autorizata pentru .campion

Procedura de deplasare a coordonatelor cu valoarea


dup axa Ox i cu valoarea vy dup axa Oy poate fi
realizat n modul urmtor:
vx

procedure move(var P:point; vx,vy:real);


begin
P.x:=P.x+vx;
P.y:=P.y+vy;
end;

La fel de simpl este i o posibil implementare a rota


iei cu un unghi u fa de un punct de coordonate vx, vy:
procedure rotate (var P:point; u,vx,vy:real);
var
old:point;
begin
old:=P;
P.x:=vx+(old.x-vx)*cos(u*pi/180)
-(old.y-vy)*sin(u*pi/180);
P.y:=vy +(old.x-vx)*sin(u*pi/180)
+(old.y-vy)*cos(u*pi/180);
end;

11

Copie autorizata pentru .campion

2. Intersecii
n majoritatea proble
melor de geometrie compu
taional apare n calitate de
subproblem determinarea
coordonatelor punctului de
intersecie a dou drepte, a
dou segmente sau a unui
segment i unei drepte.

Fig. 2.1. Definirea dreptei (segmentului) prin dou puncte

Metoda folosit pentru rezolvarea acestor subprobleme


este aceeai, cu diferene puin semnificative pentru fiecare caz.
Att pentru definirea dreptei, ct i pentru definirea
segmentului se vor folosi dou puncte distincte: arbitrare
(ale dreptei) sau extreme (pentru segment)(fig. 2.1).
Prin urmare, att descrierea dreptei, ct i descrierea segmentului pot fi realizate de aceeai structur de
date, care va conine coordonatele a dou puncte i, suplimentar, coeficienii A, B, C ai ecuaiei generale a dreptei.
Aceti coeficieni vor fi necesari pentru calculul coordonatelor punctului de intersecie. Una din posibilele metode de definire a acestei structuri este:
type line=record
x1,y1,x2,y2 : real;
A, B, C : real;
end;

2.1. Intersecia dreptelor


Ecuaia general a dreptei

Fie dreapta l determinat de punctele p1 de coordonate ( x1 , y1 ) i p2 de coordonate ( x2 , y2 ) . Ecuaia dreptei


12

Copie autorizata pentru .campion

ce trece prin aceste dou puncte este:

x x1
y y1
=
.
x2 x1 y2 y1

(2.1)

Din aceast ecuaie pot fi calculai coeficienii ecuaiei


generale a dreptei: Ax + By + C = 0 .
Prin transformri elementare din (2.1) se obine:

x( y2 y1 ) + y ( x1 x2 ) + ( x2 y1 x1 y2 ) = 0. (2.2)
Din (2.2) rezult formulele de calcul pentru coeficienii
ecuaiei generale:

A = y2 y1 ,

B = x1 x2 ,

(2.3)

C = x2 y1 x1 y2 .
Determinarea punctului de intersecie
a dou drepte
Fie dreptele p i l determinate de perechile de puncte
p1 ( x1 , y1 ) , p2 ( x2 , y2 ) i respectiv p3 ( x3 , y3 ) , p4 ( x4 , y4 ) .
Determinarea punctului q de intersecie a acestor
drepte se reduce la rezolvarea sistemului de ecuaii:

A1 x + B1 y + C1 = 0

A2 x + B2 y + C2 = 0,
unde A1 x + B1 y + C1 = 0 este ecuaia general a dreptei p
i A2 x + B2 y + C2 = 0 este ecuaia general a dreptei l.
Coeficienii acestor ecuaii pot fi calculai conform formulelor (2.3).
Pn la rezolvarea nemijlocit a sistemului urmeaz
s se verifice dac dreptele p i l sunt paralele sau coincid.
13

Copie autorizata pentru .campion

Pentru aceasta se verific condiiile:


a) A1 B2 = A2 B1 & A1C2 A2C1 dreptele p i l sunt


paralele;
b) A1 B2 = A2 B1 & A1C2 = A2C1 dreptele p i l coincid.

Dac niciuna din condiiile precedente nu se satisface,


atunci exist un punct unic de intersecie a dreptelor p
i l, ale crui coordonate pot fi calculate dup formulele:
a) dac A1 0 ,

ysol =

C1 A2 A1C2
,
B2 A1 B1 A2

B y + C1
xsol = 1 sol
;
A1

b) dac A1 = 0 ,
C
ysol = 1 ,
B1

xsol

B y + C2
= 2 sol
.
A2

(2.4 a)

(2.4 b)

Cu ajutorul setului de formule (2.4) pot fi calculate coordonatele punctului de intersecie q a dreptelor p i l.

2.2. Intersecia dreptei cu un segment


Formulele deduse n paragraful precedent permit s
se calculeze coordonatele punctului de intersecie a dou
drepte. Cazul interseciei a dou segmente sau a unei
drepte i a unui segment pot fi reduse la cel al interseciei
dreptelor, dar cu verificarea unor condiii suplimentare.
Fie dreapta l care trece prin punctele p1 , p2 i segmentul s cu punctele extreme s1 , s2 .
14

Copie autorizata pentru .campion

Se observ c n cazul interseciei dreptei l i a segmen


tului s, extremitile segmentului
sunt poziionate de pri

diferite fa de vectorul p2 p1 . Dac obiectele cercetate nu


se intersecteaz, atunci ambele extremiti
ale segmentului se afl de aceeai parte a vectorului p2 p1 (fig. 2.2).

Fig. 2.2. Poziia segmentului fa de dreapt

Poziia punctului fa de un vector

Fie vectorul p2 p1 de coordonate ( x2 , y2 ) , ( x1 , y1 ) i


punctul s de coordonate ( x3 , y3 ) .

Pentru a poziiona punctul s fa de vectorul p2 p1 ,


poate fi folosit urmtorul determinant [12, p. 60]:

x2
= x1
x3

y2 1
y1 1 .
y3 1

Determinantul este pozitiv, dac punctul


s este situat
n semiplanul drept fa de vectorul p2 p1 ; este nul, dac
punctul s aparine dreptei determinate de acest vector;
este negativ, dac s este situat n semiplanul stng.
O realizare posibil a funciei de calcul al determinantului este urmtoarea:
function sarrus(p1,p2,p3:point ): real;
begin
sarrus:= p1.x*p2.y+p2.x*p3.y+p1.y*p3.x
-p3.x*p2.y-p3.y*p1.x-p1.y*p2.x;
end;
15

Copie autorizata pentru .campion


Expresia Sarrus(p2,p1,s1)*Sarrus(p2,p1,s2)

va avea
valoare: pozitiv, dac dreapta l i segmentul s nu se in
tersecteaz (ambele extremiti ale segmentului sunt
situate de aceeai parte a dreptei, valorile determinantului sunt de acelai semn); nul, dac cel puin una dintre
extremiti aparine dreptei (pentru extremitatea segmentului care aparine dreptei, determinantul este egal cu 0);
negativ, dac dreapta l i segmentul s se intersecteaz
(extremitile segmentului sunt situate de pri diferite
ale vectorului, valorile determinantului au semne dife
rite).
Prin urmare, dac pentru dreapta l determinat de
punctele p1 i p2 i segmentul s cu extremitile s1 i s2
expresia Sarrus(p2,p1,s1)*Sarrus(p2,p1,s2) are valoare
negativ, atunci dreapta l i segmentul s se intersecteaz,
iar coordonatele punctului de intersecie pot fi calculate
conform formulelor (2.4).
Dac valoarea expresiei este nul, se verific nemijlocit
care dintre extremitile segmentului aparine dreptei. n
cazul n care ambele extremiti ale segmentului aparin
dreptei, ntreg segmentul este coninut de aceasta.

2.3. Intersecia segmentelor


Fie segmente s i p cu extremitile s1 , s2 , respectiv
p1 , p2 . Pentru simplitate se va considera c segmentele
nu aparin aceleiai drepte i nu sunt paralele (cazurile
date pot fi verificate cu ajutorul precondiiilor pentru formulele (2.4)).
Segmentele se vor intersecta numai dac
Sarrus(p2,p1,s1)*Sarrus(p2,p1,s2) 0 i
Sarrus(s2,s1,p1)*Sarrus(s2,s1,p2) 0.
16

Copie autorizata pentru .campion

3. nfurtoarea convex
Problema determinrii nfu
rtoarei convexe este una dintre
problemele centrale ale geometriei
computaionale. Ea apare att n
cadrul unor aplicaii economice, financiare, ecologice, arhitecturale,
ct i n probleme geometrice ana
litice.
Fig. 3.1. nfurtoarea
Noiunea de nfurtoare con convex a unei mulimi de
puncte
vex n plan este intuitiv simpl:
pentru o mulime S de puncte ale planului, nfurtoarea
convex Q ( S ) este mulimea de vrfuri ale poligonului1
convex cu cea mai mic arie, care conine toate punctele
mulimii S. nfurtoarea convex poate fi modelat cu
ajutorul inei benzi elastice, ntinse n jurul mulimii S. La
eliberare, banda elastic va repeta conturul nfurtoarei
convexe (fig. 3.1).

3.1. Algoritmul elementar


Fie mulimea de puncte din plan S = { p1 , ... , pN } . Fiecare element pi al mulimii este descris prin coordonatele
sale carteziene ( xi , yi ) . O metod intuitiv de determina
re a nfurtoarei convexe presupune eliminarea din
mulimea iniial a tuturor punctelor ei interioare.
Poligon figur geometric plan, nchis, format dintr-un numr
finit de segmente, numite laturi. Aici i n continuare prin poligon se va
nelege frontiera acestuia n reuniune cu interiorul su. Poligonul P
este convex, dac x1 , x2 P, [x1 , x2 ] P . Poligonul P este simplu, dac
laturile lui se intersecteaz doar n extremitile lor.
1

17

Copie autorizata pentru .campion

Algoritmul elementar se bazeaz pe dou afirmaii


simple:
a) nfurtoarea convex a unei mulimi de puncte

S este format din punctele extreme ale mulimii S;


b) un punct p S nu este un punct extrem dac i


numai dac exist cel puin un triunghi, determinat
de punctele pi , p j , pk S , astfel nct p s-i aparin
(fig. 3.2).

n baza acestor afirmaii, punc


tele interioare ale mulimii se exclud prin cercetarea apartenenei
fiecrui punct la fiecare triunghi
generat de punctele mulimii. Att
pseudocodul, ct i implementarea
algoritmului sunt extrem de simple:

Fig. 3.2. Determinarea unui


punct interior

Pseudocod
Pas 1 C S
Pas 2 Pentru toate punctele pi S
Pentru toate punctele p j S , p j pi
Pentru toate punctele pk S , pk pi , pk p j
Pentru toate punctele

p S , p pi , p p j , p pk
if

p pi p j pk

18

then

C C /{ p}

Copie autorizata pentru .campion

Apartenena punctului la un triunghi

Condiia p pi p j pk poate fi verificat prin determi

pi p j ,
narea
poziiei
punctului
p
fa
de
fiecare
din
vectorii

p j pk , pk pi . Dac semnul valorilor returnate la apelurile


funciei sarrus(pi,pj,p), sarrus(pj,pk,p), sarrus(pk,pi,p)
este acelai, atunci p pi p j pk . Prin urmare, verificarea
apartenenei punctului la un triunghi poate fi realizat
ntr-un numr de operaii mrginit de o constant.
Instruciunile ciclice din pasul 2 al algoritmului gene
reaz un numr de operaii proporional cu N 4 , ceea ce de
4
termin i complexitatea final a algoritmului O ( N ).
Implementare
Structura de date utilizat pentru determinarea nfurtoarei convexe este un tablou de elemente, fiecare dintre ele fiind un articol cu trei componente: coordonatele
punctului i marcajul (0 punct extrem, 1 punct interior), care specific apartenena la nfurtoarea convex:
type point=record
x,y,int: integer;
end;

Verificarea dac punctul aparine la un triunghi este


realizat de funcia apart:
function apart(l,i,j,k:integer) : boolean;
var k1,k2,k3: real;
begin apart:=true;
k1:=sarrus(a[i],a[j],a[l]);
k2:=sarrus(a[j],a[k],a[l]);
k3:=sarrus(a[k],a[i],a[l]);
if (k1*k2 <0 ) or (k1*k3<0) or (k2*k3<0)
then apart:=false;
end;

19

Copie autorizata pentru .campion

Aplicarea marcajelor este realizat n fragmentul:

for i:=1 to n-2 do


for j:=i+1 to n-1 do
for k:=j+1 to n do
for l:=1 to n do
if (l<>i) and (l<>j) and (l<>k) then
if apart(l,i,j,k) then a[l].int:=1;

Afiarea coordonatelor punctelor care formeaz nfu


rtoarea se realizeaz prin verificarea marcajelor:
for i:=1 to n do if a[i].int=0
then writeln(a[i].x, ,a[i].y);

Algoritmul descris, dei este unul polinomial, nu este


cel mai eficient pentru determinarea nfurtoarei convexe a unei mulimi de puncte.

3.2. Algoritmul Graham


Un algoritm eficient pentru determinarea nfurtoarei
convexe a fost propus de R. L. Graham n 1972. Algoritmul se bazeaz pe determinarea unui punct interior al
mulimii S, deplasarea n el a originii sistemului de coordonate i sortarea celorlalte
puncte pi ale mulimii
dup msura unghiului
format de vectorul
Opi cu axa Ox. Dup
sortare, punctele din S
sunt plasate ntr-o list
bidirecional, circular.
La urmtoarea etap se
parcurge lista format,
pornind de la punctul
3.3. Parcurgerea listei de puncte conde abscis minim (fig. Fig.
form algoritmului Graham (punctele p1, p2,
3.3). Acesta este un punct p3 marcheaz tripletul curent)
20

Copie autorizata pentru .campion

care, n mod cert, aparine nfurtoarei convexe. La


fiecare moment al parcurgerii se cerceteaz un triplet
de elemente2 consecutive ale listei p1 , p2 , p3 . Cercetarea
este realizat
prin verificarea poziiei punctului p2 fa

de vectorul p1 p3 .

Poziionarea n semiplanul stng stabilete p2 ca fiind


un punct interior al mulimii. n acest caz, p2 este exclus
din list, iar tripletul care urmeaz s fie cercetat devine
p0 , p1 , p3 ( p0 elementul precedent pentru p1 ).

Poziionarea n semiplanul drept stabilete p2 ca fiind


un punct posibil al nfurtoarei convexe. n acest caz,
p2 este pstrat n list, iar tripletul care urmeaz s fie
cercetat devine p2 , p3 , p4 ( p4 elementul urmtor pentru
p3 ). Parcurgerea ia sfrit cnd se revine n punctul de
unde a nceput.
Pseudocod
Pas 1 Se determin un punct interior z ,

z S.

Pas 2 Se transfer originea sistemului de coordonate n


punctul z.
Pas 3 Se determin coordonatele polare (r , ) ale fiec
rui punct p S , p z , apoi se sorteaz dup
creterea (pentru punctele cu unghiuri congruente sortarea se efectueaz dup creterea r).
Pas 4 Se formeaz o list bidirecional, circular, ale
crei elemente sunt punctele sortate (Q).
Pas 5 Se stabilete p0 punctul de abscis minim (n
sistemul cartezian de coordonate). p p0 .
Pas 6 Ct timp la p0 nu se ajunge prin micri nainte,
se repet:
2

Fiecare element al listei descrie un punct al mulimii S.


21

Copie autorizata pentru .campion

a) Se consider tripletul p1 p, p2 p[urm],


p3 p2 [urm] .
b) Dac p2 e poziionat
n semiplanul drept fa

p
p
de vectorul k i , atunci se efectueaz micarea
nainte: p p[urm] , altfel p2 se exclude
din lista Q i se efectueaz micarea napoi:
p p[ prec] .

Pas 7 Q nfurtoarea convex.


Complexitatea algoritmului este O ( N log N ) i e
determinat de complexitatea pasului 3 sortarea punctelor dup unghiul . Paii 1, 2, 4, 5 au o complexitate
liniar. Aceeai complexitate o are i pasul 6 la fiecare
moment fie este eliminat un punct, fie se realizeaz
un pas nainte. Numrul de operaii pentru verificarea
poziiei punctului p2 este mrginit de o constant.
Modificarea Andrew
Modificarea Andrew a algoritmului Graham are
drept scop omiterea determinrii punctului interior z, a
deplasrii originii sistemu
lui de coordonate i a calculului coordonatelor polare.
La baza variantei Andrew
st urmtorul principiu: par
tea superioar (dup y) a
nfurtoarei convexe este
bombat (n sus) pentru oricare 3 puncte consecutive ale
sale, cea inferioar bombat
n jos (fig. 3.4).
Fig. 3.4. Construirea nfurtoarei
convexe. Modificarea Andrew pentru
algoritmul Graham

22

Copie autorizata pentru .campion

Pseudocodul algoritmului are urmtoarea form:

Pas 1 Se determin dou puncte extreme pmin , pmax S


de abscis minim (respectiv maxim).
Pas 2 Se separ S n Ssup i Sinf dup poziia punctelor

din mulimea iniial fa de vectorul pmin pmax .


Ssup va fi format din punctele extreme i cele din
stnga vectorului, Sinf din punctele extreme i
cele din dreapta vectorului.
Pas 3 Se sorteaz Ssup, Sinf dup creterea abscisei.
Pas 4
a) Se verific toate tripletele de puncte consecutive
pi , pi +1 , pi + 2 Ssup , pornind de la pmin.
Dac
pi +1 este poziionat n stnga vectorului
pi pi + 2 , atunci se execut micarea nainte, altfel micarea napoi. La atingerea pmax, punctele rmase n Ssup formeaz partea superioar a
nfurtoarei convexe.

b) Se verific toate tripletele de puncte consecutive


pi , pi +1 , pi + 2 Sinf , pornind de la pmin .

Pas 5

Dac
pi +1

este poziionat n dreapta vectorului


pi pi + 2 , atunci se execut micarea nainte, altfel micarea napoi. La atingerea pmax, punctele rmase n Sinf formeaz partea inferioar a
nfurtoarei convexe.

Q Sinf Ssup .

n cele ce urmeaz este propus o realizare a acestui


algoritm. Se presupune c punctele sunt date prin coordonatele lor numere ntregi. Sortarea este realizat de procedura qsort (descrierea i implementarea poate fi gsit,
23

Copie autorizata pentru .campion

de exemplu, n [7, 303]). Poziia reciproc a punctelor este


determinat de funcia sarrus, descris anterior.
Structurile de date:
drag mulimea S
sus, jos mulimile Ssup, Sinf
n |S|

procedure conv;
var minx,maxx:longint;
j, imin, imax,i, nsus, njos: integer;
rem: boolean;
p1,p2,p3:nod;
begin
{1. determinarea extremelor dupa x}
minx:=drag[1].x; maxx:=drag[1].x;imin:=1; imax:=1;
for i:=2 to n do
if drag[i].x< minx then
begin minx:=drag[i].x; imin:=i; end
else if drag[i].x>maxx then
begin maxx:=drag[i].x; imax:=i; end;
{2. separarea in submultimi}
nsus:=1; njos:=1;
sus[1]:=drag[imin]; jos[1]:=drag[imin];
for i:=1 to n do
if not (i in [imin, imax])then
if sarrus(drag[imin],drag[imax],drag[i])<0
then
begin inc(njos); jos[njos]:=drag[i]; end
else
begin inc(nsus); sus[nsus]:=drag[i]; end;
inc(nsus);sus[nsus]:=drag[imax];
inc(njos);jos[njos]:=drag[imax];
{3. sortarea subseturilor }
qsort(sus,2,nsus-1);
qsort(jos,2,njos-1);
{crearea infurtoarei convexe}
{4. sus}
repeat
rem:=false; i:=2;
24

Copie autorizata pentru .campion


while i<nsus do
begin
p1:=sus[i-1]; p2:=sus[i]; p3:=sus[i+1];
if sarrus(p1,p3,p2)>0 then i:=i+1
else begin
rem:=true;
for j:=i to nsus-1 do
sus[j]:=sus[j+1];
dec(nsus);
end;
end;
until not rem;
{si jos}
repeat
rem:=false; i:=2;
while i<njos do
begin
p1:=jos[i-1]; p2:=jos[i]; p3:=jos[i+1];
if sarrus(p1,p3,p2)<0 then i:=i+1
else begin
rem:=true;
for j:=i to njos-1 do
jos[j]:=jos[j+1];
dec(njos);
end;
end;
until not rem;
{5. asamblarea}
for i:= nsus-1 downto 2 do
begin
inc(njos);
jos[njos]:=sus[i];
end;
drag:=jos; n:=njos;
end;{conv}

La finalul execuiei procedurii punctele care formeaz


nfurtoarea convex vor fi stocate n structura de date
jos.

25

Copie autorizata pentru .campion

4. Triangularizri
Din punct de vedere geometric, triangularizarea T(S)
a mulimii de puncte S este
o divizare a nfurtoarei
convexe Q(S) n triunghiuri.
Suplimentar, se vor respecta
condiiile:
a) vrfri ale triunghiurilor

pot fi numai puncte
Fig. 4.1. Triangularizarea unei mul

din S;
imi de puncte
b) toate punctele mulimii

S vor fi utilizate n calitate de vrfuri (fig. 4.1).

4.1. Un algoritm greedy


pentru mulimi de puncte
Fie mulimea de puncte S i N=|S|. Fiecare punct p S
este descris prin coordonatele sale carteziene ( x, y ) . Triangularizarea T(S) poate fi cercetat ca un graf planar cu
mulimea de noduri S. Prin urmare, numrul de laturi
M n S este proporional cu N (conform formulei Euler,
M 3 N 6 ).
O soluie simpl n plan este generarea tuturor segmentelor posibile cu extremiti n S, sortarea lor dup
lungime, apoi adugarea consecutiv n triangularizare.
n proces se verific dac latura curent intersecteaz laturile adugate anterior. Dac interseciile lipsesc, latura
este adugat, n caz contrar, se trece la cercetarea laturii
urmtoare.
26

Copie autorizata pentru .campion

Numrul total de laturi posibile pe punctele din S este


N 2 2 . Fiecare latur poate fi cercetat ca un segment de-

scris prin extremitile sale:

type segment=record
p1,p2:nod; l:real;
end;

Prin urmare, verificarea interseciei laturilor poate fi


realizat folosind o procedur identic cu procedura de
verificare a interseciei segmentelor ( 2.3).
Function intersect (A,B: segment): boolean;
Begin
if sarrus(A.p2,A.p1,B.s1)*sarrus(A.p2,A.p1,B.s2) 0 and
sarrus(B.s2,B.s1,A.p1)*Sarrus(B.s2,B.s1,A.p2) 0
then
intersect:= true else intersect:= false
End;

Calculul distanei3 dintre dou puncte pi , p j S (lungi


mea laturii) poate fi realizat printr-o funcie elementar:
Function distant (p[i],p[j]: nod): real;
Begin
distant:=
sqrt(sqr(p[i].x-p[j].x)+ sqr(p[i].y-p[j].y));
End;

Pseudocod
Pas 1 m 0
Pas 2 for i 1 to N do
for j 1+i to N do
Begin



End;

m
Latura[m].l distant(p[i],p[j])
Latura[m].st p[i]
Latura[m].fin p[j]

Pas 3 qsort(Latura,m);
3

Pentru dou puncte a, b date prin coordonatele ( xa , ya ), ( xb , yb ) ,

d ( a, b) =

xa xb + ya yb .
27

Copie autorizata pentru .campion

Pas 4 k 0

Pas 5 for i 1 to M do

begin
z false
for j 1 to k do

if intersect(Latura[i],Triang[j])
then z true
if NOT z then
begin
k ; Triang[k] Latura[i]
end;
end;

Numrul total de laturi generate este proporional


2
cu N . Sortarea lor va necesita un numr de operaii
proporional cu N 2 log( N ) . Complexitatea pasului 5 este
determinat de numrul de verificri ale interseciilor,
care nu depete N 3 . Prin urmare, complexitatea algoritmului greedy este O ( N 3 ) , ceea ce las de dorit pentru
valori mari ale lui N.

4.2. Triangularizarea poligoanelor convexe


Este o problem elementar, care poate fi rezolvat n
timp liniar.
Fie P un poligon convex, dat
prin lista vrfurilor p1, ... ,pN n
ordinea parcurgerii lor. Pentru
a construi o triangularizare n
P, este suficient s fie construite segmentele diagonale p1 p3 ,
..., p1 pN 1 (fig. 4.2). Numrul
diagonalelor este proporional
cu N (numrul de vrfuri ale
poligonului). Construirea unei Fig. 4.2. Triangularizarea unui poligon convex
diagonale necesit un numr
28

Copie autorizata pentru .campion

constant de operaii. Triangularizarea poligonului convex


poate fi util pentru calculul ariei lui. Aria poligonului este
egal cu suma ariilor triunghiurilor din triangularizare.

4.3. Triangularizarea poligoanelor simple


Metoda greedy
n cazul poligoanelor simple nu este posibil de a realiza
direct metoda din compartimentul precedent, deoarece
apar dou condiii suplimentare care trebuie verificate:
1) aparine oare latura curent poligonului sau exteriorului poligonului triangularizat;
2) laturile care formeaz frontiera poligonului urmea
z s fie incluse n triangularizare indiferent de locul
ocupat n lista distanelor.
Verificarea primei condiii este echivalent cu verifica
rea apartenenei mijlocului laturii la poligon. Algoritmul
care rezolv aceast problem este prezentat n 5.1.
Problema a doua se rezolv elementar: prin includerea
laturilor ce formeaz frontiera P n nceputul listei care
descrie triangularizarea.
Fie P un poligon simplu, dat prin lista de vrfuri
p1, ..., pN , n ordinea parcurgerii lor. Algoritmul greedy va
fi descris de urmtorul pseudocod:
Pas 1 m 0
Pas 2 for i 1 to N do
for j 2+i to N do
Begin
m
Latura[m].l

distant(p[i],p[j])

29

Copie autorizata pentru .campion


Latura[m].st p[i]
Latura[m].fin p[j]
End;

Pas 3 qsort(Latura,m);

Pas 4 for i 1 to N-1 do

Begin
Triang[i].st p[i]
Triang[i].fin p[i+1]
End;
Triang[N].st p[N]
Triang[N].fin p[1]
k N

Pas 5 for i 1 to M do

Begin
z false
for j 1 to k do


if intersect(Latura[i],Triang[j])
then z true
if NOT z then
Begin
x,y middle(Latura[i])

if apart(x,y,P)then
Begin

k ; Triang[k] Latura[i]
End;
End;
End;

Calculul coordonatelor mijlocului segmentului necesit


un numr constant de operaii:
Procedure middle(a: segment; var x,y:real);
Begin
x:=(a.st.x+ a.fin.x)/2; y:=(a.st.y+ a.fin.y)/2;
End;

Verificarea apartenenei unui punct la un poligon are o


complexitate liniar fa de numrul N de laturi ale aces
tuia. Prin urmare, complexitatea pasului 5 i complexi
tatea total a algoritmului rmne aceeai ca i pentru
algoritmul descris n 4.1.
30

Copie autorizata pentru .campion

5. Apropiere i apartenen
Capitolul este consacrat analizei unor probleme geometrice n plan: determinarea celei mai apropiate perechi de
puncte, apartenena punctului la un poligon, construcia
poligoanelor cu proprieti prestabilite. Soluiile directe ale
acestor probleme sunt relativ simple, dar nu i optime.

5.1. Cea mai apropiat pereche de puncte


Fie n plan o mulime de
puncte S = {s1 ,..., sN }. Se cere
s se determine o pereche de
*
*
puncte (fig. 5.1) si , s j , i j :

d ( si* , s*j ) = min d ( si , s j ).


i =1,..., N
j =1,..., N
i j

Calculul direct al tuturor


distanelor dintre N puncte
necesit un numr de operaii
2
proporional cu N :

Fig. 5.1. Cea mai apropiat pereche


de puncte

index1 1; index2 2;
min distance(s1, s2);
For i 1 to N do
For j 1+i to N do
If distance(si, sj) < min then
Begin
min distance(si, sj)

index1 i; index2 j;
End;

Acelai rezultat poate fi obinut ntr-un timp mai restrns, folosind algoritmul optim cu o complexitate de
O( N log N ) .
31

Copie autorizata pentru .campion

Algoritmul optim

Pentru a determina n
timp optim cea mai apro
piat pereche de puncte,
poate fi folosit tehno
logia recursiv desparte i
stpnete. Ideea major
este divizarea, la fiecare
Fig. 5.2. Divizarea mulimii n submulimi
pas recursiv, a mulimii separabile fa de dreapta l pentru reiniiale n dou submulimi zolvarea recursiv a problemei cea mai
liniar separabile i rezol- apropiat pereche de puncte
varea problemei pe fiecare
submulime n parte (fig. 5.2).
Cazul elementar, care permite calculul direct al soluiei,
este mulimea format din dou sau trei puncte. Numrul
de operaii la acest pas este constant. Specificul problemei
const n determinarea soluiei optime la etapa de asamblare: avnd dou submulimi S1 i S2, cea mai apropiat
pereche de puncte n S1 S 2 poate s fie determinat de
o pereche s, s : s S1 , s S 2 . Se poate demonstra c, la
etapa asamblrii soluiei, numrul necesar de verificri la
fiecare nivel este liniar fa de numrul de puncte din mul
imile asamblate. Numrul de divizri consecutive ale mul
imii n submulimi balansate4 nu va depi log( N ) . Dac
numrul de operaii necesare pentru determinarea soluiei
la un nivel de asamblare este proporional cu N, complexitatea final a algoritmului va fi O ( N log N ) . Pentru
soluionarea optim a problemei este necesar o preprocesare a mulimii: sortarea punctelor dup abscis (se obine
irul sortat X) i sortarea punctelor dup ordonata lor (se
obine irul sortat Y). Avnd complexitatea O ( N log N ) ,
sortarea nu modific complexitatea final a algoritmului.
4

Numrul de elemente din fiecare submulime difer cu cel mult 1.


32

Copie autorizata pentru .campion

Fie la un nivel de divizare mulimea S, irul X al ele


mentelor din S sortate dup abscisa x, irul Y cu elemen
tele S sortate dup ordonata y.
Aparent, procesul de asamblare a soluiei la un nivel
2
dat are o complexitate O ( N ) : maxim N puncte n S1 i
maxim N puncte n S2, dintre care urmeaz s fie calculate distanele. n realitate,
numrul de operaii este
mult mai mic.
Fie S a fost divizat n
submulimile S1 i S2, pe
care au fost determinate
distanele minime 1 i
2 , precum i perechile Fig. 5.3. Determinarea punctelor poten
respective de puncte. Se
iale pentru soluia pe S1 S 2
consider = min(1 , 2 )
(fig. 5.3).
Pentru determinarea soluiei optime pe S1 S 2 este
necesar de a cerceta doar punctele situate n fia de
lime de la dreapta l care separ submulimile. Celelalte puncte din submulimi se afl, evident, la o distan
mai mare dect unul de altul i nu pot mbunti
soluia. Aceast restrngere nu garanteaz efectuarea
unui numr liniar de operaii,
deoarece pentru un punct cer
cetat s S1 n fia poate fi un
numr de puncte proporional cu
S 2 . O analiz mai detaliat permite excluderea din cercetare a
tuturor punctelor care se afl n
exteriorul dreptunghiului de dimensiunile 2 , asociat pun
ctului s (fig. 5.4). Numrul de Fig. 5.4. Zona de cercetare n
puncte ale mulimii S2 care se pot S2 pentru un punct dat s S1
33

Copie autorizata pentru .campion

afla n aceast zon nu poate fi


mai mare dect 6. Prin urmare,
numrul de verificri la etapa de
asamblare nu va depi 6N.
Folosind irurile X i Y, se
formeaz irul Y , care conine
punctele din S situate n fia
[l , l + ] , sortate dup y
5.5. Numrul elementelor
mulimea punctelor care pot Fig.
consecutive Y care pot modifica
mbunti soluia. Pentru fie distana minim nu depete 9
care element din Y se calcu
leaz distanele doar pn la urmtoarele 8 elemente: ele
reprezint (n cel mai ru caz) simetric 6 puncte din S2
plus 6 puncte din S1 minus 3 puncte care coincid, minus
punctul cercetat (fig. 5.5).
Pseudocod
Preprocesare
X S, sort(X)

{sortare dup x}

Y S, sort(Y)

{sortare dup y}

Procedure apr2p(S, X, Y)
If

S 4

then

formeaz S1 , S 2 , X 1 , X 2 , Y1 , Y2
min (apr2p( S1 , X 1 , Y1 ),apr2p( S 2 , X 2 , Y2 ))
formeaz Y
for i 1 to Y do

for j 1 to 8 do
if distance( Y [i], Y [i+j]) <
then distance ( Y [i], Y [i+j])
return
end elsereturn distana minim n S {calculat direct}
begin

34

Copie autorizata pentru .campion

5.2. Apartenena punctului la un domeniu


Apartenena punctului la un poligon convex

Problema determinrii apar


tenenei unui punct la un poligon convex este una simpl i
poate fi rezolvat cu ajutorul algoritmilor cercetai anterior. Se
observ uor (fig. 5.6) c poziia
unui punct interior fa de fiecare din vectorii determinai de
vrfurile consecutive ale poliFig. 5.6. Punctele interioare sunt
gonului este una i aceeai la plasate de aceeai parte a vecto
dreapta, dac vrfurile sunt par- rilor determinai de vrfurile consecutive ale poligonului, poziia
curse n direcia micrii acelor celor exterioare poate varia.
de ceasornic, i la stnga, n
cazul parcurgerii vrfurilor n
direcie opus.

Poziia punctului s fa de un vector pi p j poate


fi determinat n timp constant ( 3.1). Prin urmare,
complexitatea algoritmului este proporional doar cu
numrul de laturi ale poligonului. Fie punctul s de coordonate (xs , ys) i poligonul convex P = ( p1 , p2 , ... , pN ) cu
N laturi, descris prin lista vrfurilor parcurse consecutiv
(coordonatele vrfurilor sunt stocate n tabloul liniar de
articole P cu cmpurile x i y). Pentru a simplifica implementarea, n lista de vrfuri ale poligonului este inclus un
vrf virtual pN +1 p1 .
function apart : boolean;
var i : integer;
function verific_punct(x1,y1,x2,y2,x3,y3:real):boolean;
begin
if x1*y2+x2*y3+y1*x3-x3*y2-x2*y1-y3*x1 > 0 then
verific_punct:=true else verific_punct:=false;
end;
35

Copie autorizata pentru .campion

begin {apart}
apart:=true;
for i:=1 to N do
if not
verific_punct(p[i].x,p[i].y,p[i+1].x,p[i+1].y,s.x,s.y)
then apart:=false;
end; {apart}

Apartenena punctului la un poligon stelat


Fie un poligon arbitrar
P = ( p1 , p2 , ... , pN ) cu N laturi.
Dac n P exist un punct interi
or c, astfel nct toate intervalele
[c, p1 ],[c, p2 ],...,[c, pN ] aparin
integral P, poligonul se numete
stelat (fig. 5.7).
n cazul n care punctul interior c este cunoscut apriori, Fig. 5.7. P - poligon stelat
determinarea apartenenei unui
punct arbitrar s la poligonul P se reduce la verificarea
existenei unui triunghi5 cpi pi +1 , i = 1, N , care s conin
punctul s n calitate de punct interior.
Numrul triunghiurilor este N, numrul de operaii
necesare pentru verificarea apartenenei punctului la
interiorul unui triunghi este mrginit de o constant. Prin
urmare, complexitatea determinrii apartenenei punctului la un poligon stelat va fi O ( N ) n condiia c punctul
c este cunoscut.
Apartenena punctului la un poligon simplu
Problema apartenenei unui punct s la un poligon simplu P poate fi rezolvat prin triangularizarea P i prin
5

Vrful pN+1 este unul virtual i coincide cu p1.


36

Copie autorizata pentru .campion

verificarea ulterioar a apartenenei s la unul din triunghiurile formate n procesul triangularizrii.


Un algoritm mai eficient este bazat pe numrarea
interseciilor ale dreptei orizontale l care trece prin
punctul dat s cu laturile poligonului P (fig. 5.8). Se va cerceta partea dreptei spre stnga
de s. Pentru latura curent se
determin:
poziia punctului fa de
aceasta;
intersecia laturii cu semidreapta l.
Dac numrul interseciilor
spre stnga de s este impar,
Fig. 5.8. Numrul de intersecii
punctul se afl n interiorul po- ale semidreptei l cu laturile poliligonului; pentru un numr par gonului determin apartenena
punctului s la poligonul P
de intersecii, punctul se afl n
exterior. Demonstraia este elementar: la parcurgerea
spre stnga, prima intersecie marcheaz intrarea semidreptei n interiorul poligonului, urmtoarea ieirea.
Fiecare pereche urmtoare de intersecii are aceeai
semnificaie.
Pentru stabilirea interseciei semidreptei cu latura
curent pot fi utilizate metodele descrise n 2.2.
Cazuri speciale
A. Dreapta l trece printr-un vrf pi al
poligonului P la stnga de s. Vrfurile pi-1 i pi+1 se afl de pri
diferite ale dreptei l. Numrul de
intersecii se incrementeaz cu
1.
37

Copie autorizata pentru .campion

B. Dreapta l conine latura pi-1 pi+1 a


poligonului P la stnga de s. Vrfurile pi-1 i pi+2 se afl de pri
diferite ale dreptei l. Numrul
de intersecii se incrementeaz
cu 1.
C. Dreapta l trece printr-un vrf
pi al poligonului P la stnga
de s. Vrfurile pi-1 i pi+1 se afl
de aceeai parte a dreptei l.
Numrul de intersecii nu se
incrementeaz.
D. Dreapta l conine latura pi-1 pi+1 a
poligonului P la stnga de s. Vrfurile pi-1 i pi+2 se afl de aceeai
parte a dreptei l. Numrul de
intersecii nu se incrementeaz.
Numrul de laturi procesate este N. Determinarea
interseciei laturii cu dreapta l este realizat ntr-un
numr constant de operaii. Procesarea cazurilor speciale
este realizat de asemenea ntr-un numr de operaii
mrginit de o constant. Prin urmare, complexitatea algoritmului este O ( N ) .

38

Copie autorizata pentru .campion

5.3. Poligonul i diagrama Voronoi

O alt problem de apro


piere n plan este problema
determinrii poligonului Vo
ronoi pentru o mulime de
puncte.
Fie n plan mulimea de
puncte S = { p1 ,..., pN } . Fiecare punct
pi , i = 1, N ,
este descris de coordonatele
carteziene (xi , yi). Pentru un
punct dat pi S se cere s se Fig. 5.9. Poligonul Voronoi V(i) pentru
determine poligonul V(i) care punctul pi.
va conine toate punctele
planului, mai apropiate de
pi dect de oricare alt punct
p j S , pi p j (fig. 5.9).
Problema
generalizat
pentru toate punctele mul
imii S este cunoscut sub
numele diagrama Voronoi
(fig. 5.10).
De menionat c pentru
unele puncte ale mulimii
Fig. 5.10 Diagrama Voronoi pentru
S, domeniul determinat de mulimea S
poligonul Voronoi poate fi
unul infinit. Se poate demonstra c aceast proprietate o
posed punctele care formeaz nfurtoarea convex a
mulimii S.
Algoritmul direct pentru determinarea poligonului
Voronoi V(i) se bazeaz pe urmtoarea observaie:
Dreapta l, perpendicular pe segmentul pi pj i care tre
ce prin mijlocul acestuia, conine punctele egal deprtate
39

Copie autorizata pentru .campion

att de pi , ct i de pj. Punctele mai apropiate de pi dect


de pj vor forma semiplanul determinat de dreapta l i care
conine punctul pi.
Fiecare punct p S este descris prin coordonatele sale
carteziene (x, y). Prin urmare, pentru perechea de puncte
pi, pj ,
mijlocul m al segmentului pi pj va fi determinat de
punctul de coordonate:

xm =
ym =

xi + x j

2
yi + y j

,
;

2

dreapta d care conine segmentul pi pj va fi descris
de ecuaia Ax+By+C = 0, unde
A = y j yi ,

B = xi x j ,
C =x y x y ;

j i
i j

orice dreapt lperpendicular pe segmentul pi pj va
avea ecuaia general de forma Ax+By+C= 0;
pentru dreapta l, perpendicular pe segmentul pi pj i
care trece prin punctul de mijloc al acestuia, valoa
rea coeficientului C este: Aym Bxm.
Odat ce este cunoscut ecuaia dreptei l, perpendicu
lare pe segmentul pi pj n mijlocul acestuia, poate fi determinat semiplanul R( j): p R ( j ), d ( p, pi ) < d ( p, p j ).
R( j ).
Atunci V (i ) =

j =1,.., N
j i

Pentru realizarea algoritmului poate fi construit un poligon R de restrngere a planului, astfel nct S R . Cel
mai simplu poligon R este un dreptunghi avnd laturile
paralele cu axele de coordonate, determinat de punctele
40

Copie autorizata pentru .campion

diagonale (xmin, ymin), (xmax, ymax):


xmin = min ( xi ) 1 , xmax = max ( xi ) + 1 ,
i =1,..., N

i =1,..., N

ymin = min ( yi ) 1 , ymax = max ( yi ) + 1 .


i =1,..., N

i =1,..., N

Complexitatea algoritmului direct pentru construirea


poligonului Voronoi V(i) este O ( N 2 ) :
Etapa 1: Determinarea poligonului de restrngere
necesit un numr de operaii proporional cu N.
Etapa 2: Determinarea ecuaiei dreptei l, perpendi
culare pe segmentul pi pj , necesit un numr de operaii
mrginit de o constant.
Etapa 3: Determinarea interseciei dreptei l cu poligonul R i restrngerea ulterioar a acestuia necesit un
numr de operaii proporional cu numrul de laturi ale
poligonului R (nu mai mare dect N).
Etapele 23 se repet pentru toate punctele
p S , p pi . Prin urmare, numrul de operaii nece
sare pentru determinarea poligonului Voronoi va fi
proporional cu N 2 .
Nu este eficient de a aplica direct algoritmul descris
anterior pentru determinarea diagramei Voronoi: complexitatea lui crete pn la O ( N 3 ) .
Pentru realizarea eficient a algoritmului de determi
nare a diagramei Voronoi se aplic tehnica divizrii consecutive a problemei n mulimi liniar separabile, pn la
atingerea cazurilor elementare, i asamblarea ulterioar
a soluiei [12, pag. 258 269].
Fie S = S1 S 2 i au fost construite diagramele Voronoi
DV ( S1 ), DV ( S2 ) (fig. 5.11). Pentru asamblarea soluiei
vor fi realizate urmtoarele etape:
Etapa 1: Determinarea vectorilor de intrare (ieire) ai
lanului de concatenare: se construiesc laturile lips (dou
41

Copie autorizata pentru .campion

la numr) pentru nf
urtoarea
convex
comun a
mulimii
S1 S 2 , se determin
mijloacele acestor laturi m1, m2. Prin punctele m1, m2 se traseaz
vectorii perpendiculari
pe laturile adugate la
nfurtoarea conve
x. Pentru latura supe
rioar vectorul este
orientat spre latur,
pentru cea inferioar
de la ea (fig. 5.12). Din
nfurtoarea convex
pentru S1 S 2 sunt
eliminate lanurile interioare de laturi ale
nfurtoarelor separate pentru S1 i S2.
Etapa 2: Construirea
lanului de concatenare.
Construcia lanului ncepe pe vectorul superior, dintr-un punct care
precede toate intersec
iile vectorului cu razele
diagramelor construite
anterior.
Lanul se traseaz
de-a lungul vectorului,
pn la intersecia cu

Fig. 5.11. Diagramele Voronoi DV(S1) i DV(S2)


pn la concatenare.

Fig. 5.12 Construirea


nfurtoarei convexe
pentru S prin adugarea
laturilor. Trasarea vectorilor de intrare (ieire) ai
lanului de concatenare

Fig. 5.13. Construirea lanului de conca


tenare

42

Copie autorizata pentru .campion

una din laturile diagramelor DV(S1) sau DV(S2). n punctul de


intersecie direcia vectorului se modific (fig. 5.13).
Modificarea direciei lanului este determinat de modifi
carea perechii de puncte ntre care se traseaz acesta. Fie,
iniial, lanul marcheaz frontiera dintre punctele pi i
pj. Atingerea unei laturi a diagramelor construite anterior
semnific fie nlocuirea pi prin pk (dac latura atins separ
punctul pi de pk ), fie nlocuirea pj prin pk (dac latura atins
separ punctul pj de pk). Direcia nou a lanului de conca
tenare este determinat de perpendiculara pe segmentul
ce unete perechea nou creat i care trece prin punctul de
mijloc al acestuia. Procesul ia sfrit n momentul atingerii
vectorului inferior al lanului de concatenare.
Etapa 3: Modificarea laturilor diagramei (fig. 5.14).
Laturile infinite (semidrepte) intersectate de lanul de
concatenare se transform n segmente delimitate de
originea semidreptei i punctul de intersecie a acesteia
cu lanul de concatenare, construit la etapa 2.
Laturile finite (segmentele) i modific unul din punctele extreme, acesta
fiind nlocuit prin
punctul de intersecie
cu lanul de conca
tenare.
Laturile din DV(S1),
situate integral n
dreapta de lanul de
concatenare, i latu
rile din DV(S2), situate integral n stnga
acestuia, se exclud
din diagrama final Fig. 5.14. Concatenarea diagramelor
pentru S1 S 2 .
43

Copie autorizata pentru .campion

Cazul elementar se obine pentru 2 S 3 . Procesarea acestuia este realizat printr-un numr de operaii
mrginit de o constant.
Divizarea consecutiv a mulimii pentru obinerea cazurilor elementare necesit o sortare prealabil a punctelor din S dup abscisa lor. Complexitatea preprocesrii
este O ( N log N ) . Numrul de divizri consecutive ale
mulimii curente n dou submulimi aproape egale6
este proporional cu log( N ) . Pentru concatenarea solu
iilor pariale, n cazul alegerii structurii de date adec
vate7, este necesar un numr de operaii proporional cu
numrul total de laturi din soluiile pariale. Deoarece
diagrama Voronoi este o divizare planar a unei mulimi
din N puncte, numrul de laturi va fi proporional cu N.
Prin urmare, complexitatea total a algoritmului optim
este O ( N log N ) .

5.4. Nuclee
Printre problemele geometrice de calcul se numr i
problema determinrii nucleului poligonului simplu. Nucleul unui poligon simplu P este, n general, format
din mulimea de puncte Q P , astfel nct:

x Q, y P, [ x, y ] P .
Cu alte cuvinte, nucleul poligonului este mulimea de puncte ale poligonului, astfel nct oricare dintre

6
7

Fig. 5.15. Poligon simplu


cu nucleu (partea colorat
a poligonului)

S1 este aproape egal cu S2, dac S1 S 2 1 .

O structur optim este lista bidirecional a laturilor.


44

Copie autorizata pentru .campion

ele, fiind unit cu orice alt punct al


poligonului, formeaz un segment ce
aparine n ntregime poligonului (fig.
5.15).
Nu ntotdeauna un poligon simplu
are nucleu nevid (fig. 5.16).
Nucleul poligonului (dac el exist)
este i el un poligon, dar, spre deosebire de poligonul iniial, este ntotdeauna convex.

Fig. 5.16. Poligon simplu


fr nucleu

Algoritmul pentru determinarea


nucleului unui poligon simplu
Date iniiale. Fie un poligon simplu P cu N vrfuri.
Se consider c poligonul este descris prin lista vrfurilor
sale ( p1 , p2 ,..., pN 1 , pN ) , parcurse n direcia micrii
acelor de ceasornic. Fiecare vrf pi este descris de coordonatele sale (xi , yi).
Algoritmul de determinare a nucleului necesit o
construcie secundar: un poligon convex Q care, iniial,
conine poligonul P. Pentru determinarea poligonului Q
pot fi abordate dou metode:
a) construirea nfurtoarei convexe pentru P;
b) construirea unui dreptunghi care conine P.
Metoda a doua este mult mai simpl. Ea se reduce la
determinarea, pentru coordonatele vrfurilor P, a valori
lor minime i maxime ale abscisei i ale ordonatei. n
calitate de Q poate fi considerat dreptunghiul cu vrfuri
le ( xmax + 1, ymax + 1) , ( xmax + 1, ymin 1) , ( xmin 1, ymin 1) ,
( xmin 1, ymax + 1) . Extinderea valorilor extreme nu este o
condiie obligatorie.
45

Copie autorizata pentru .campion

Dup construirea poligonului Q poate fi determinat


nemijlocit nucleul. Metoda (sau cel puin descrierea ei n
limbajul uman) este foarte simpl:
Se analizeaz consecutiv laturile poligonului P, fiind
parcurse n direcia micrii acelor de ceasornic. Latura
curent pi pi+1 se cerceteaz ca o dreapt l. Se determin
partea
poligonului Q care se afl n stnga vectorului
pi pi +1 i se exclude din Q. Dac
poligonul Q este situat
integral n stnga vectorului pi pi +1 , cercetarea ia sfrit
poligonul P nu are nucleu.
Procedeul se repet pn nu sunt analizate toate laturile poligonului P.
n final, Q conine nucleul lui P (fig. 5.17).

Fig. 5.17. Construirea consecutiv a nucleului poligonului simplu

Pseudocod
Pas 1 Iniializare

La sfritul listei de vrfuri (dup pN ) se adaug


vrful virtual pN+1. Se construiete poligonul Q
(nucleul iniial), conform uneia din metodele descrise anterior. i 1.

46

Copie autorizata pentru .campion

Pas 2 Procesarea laturii i


Fie Q = (q1 , q2 ,...qk ) . Pentru dreapta l ce conine


latura i a poligonului P definit de vrfurile pi ,
pi+1 se determin punctele de intersecie cu poligonul Q, precum i laturile intersectate. Fie d1,
d2 punctele de intersecie a dreptei l cu Q, iar laturile intersectate qj qj+1 i qk qk+1.8

a) Se formeaz poligoanele Q1 = (d1 , q j +1 , ... , qk , d 2 )


i Q2 = (d 2 , qk +1 , ... , qN , q1 , ... , q j , d1 ) .

Q {Q1 , Q2 } care se afl n dreapta


b) Se determin

vectorului pi pi +1 .

*
c) Q Q

Pas 3 Repetare

i < N then begin i goto pas 2


STOP Q este nucleul.
if

end

else

Complexitatea algoritmului este O ( N ) . Se preluc


reaz N laturi ale poligonului P. Pentru fiecare latur se
verific intersecia cu maximum N laturi ale poligonului
Q. Fiecare intersecie este determinat ntr-un numr de
operaii mrginit de o constant.
2

Dac dreapta
nu intersecteaz poligonul Q, se verific doar poziia Q
fa de pi pi +1 . Dac poligonul e poziionat n stnga, nucleul final este
vid, altfel Q nu se modific la acest pas.
8

47

Copie autorizata pentru .campion

6. Probleme geometrice de concurs


6.1. Robot

Un robot punctiform poate executa instruciuni de deplasare n 8 direcii (1 nord, 2 nord-est, 3 est, 4 sud-est,
5 sud, 6 sud-vest, 7 vest, 8 nord-vest). Lungimea pasului robotului este 1 pentru direciile 1, 3, 5, 7 i 2 pentru direciile 2, 4, 6, 8. Numrul de pai efectuai n direcia
aleas este un parametru al instruciunii de deplasare.
Fiind dat un set de instruciuni, s se determine coordonatele punctului final n care se va deplasa robotul.
Astfel, pentru setul
(1,3) (3,1) (1,1) (3,3)
(5,2) (7,1) coordonatele
finale vor fi (3,2).
S se scrie un program care, dup un set de instruciuni,
s determine coordonatele punctului final n care se va deplasa robotul. Se consider c axa Ox e orientat spre est, iar
Oy spre nord. Iniial robotul se afl n originea sistemului
de coordonate (0,0).
Date de intrare
Prima linie a fiierului de intrare conine numrul N
numrul de instruciuni (1 N 40). Urmtoarele N linii
conin instruciunile propriu-zise numrul direciei (un
numr ntreg de la 1 la 8) i numrul de pai (un numr
ntreg de la 1 la 1000), separate prin spaiu.

Date de ieire
Unica linie a fiierul de ieire va conine dou numere
ntregi x i y, separate prin spaiu, coordonatele punctului
final n care se deplaseaz robotul.
48

Exemple
date.in
6
1 3
3 1
1 1
3 3
5 2
7 1
1
8 10

Copie autorizata pentru .campion


date.out
3 2

-10 10

Rezolvare

program p01;
var
I,N:integer;
D,L,X,Y:Longint;
begin
assign(Input,date.in); reset(Input);
read(N);
X:=0; Y:=0;
{fixarea pozitiei initiale}
for I:=1 to N do
begin
{modelarea deplasarii}
read(D,L);
case D of
1: Y:=Y+L;
{ deplasare nord cu L}
2: begin X:=X+L; Y:=Y+L; end; {nord-est cu L}
3: X:=X+L;
{est cu L}
4: begin X:=X+L; Y:=Y-L; end; {sud-est cu L}
5: Y:=Y-L;
{sud cu L}
6: begin X:=X-L; Y:=Y-L; end; {sud-vest cu L}
7: X:=X-L;
{vest cu L}
8: begin X:=X-L; Y:=Y+L; end; {nord-vest cu L}
end;
end;
assign(Output,date.out); rewrite(Output);
write(X, ,Y);
close(Input); close(Output);
end.

49

Copie autorizata pentru .campion

6.2. Robot II

Sistemul de comand al unui


robot care poate executa instruc
iuni de deplasare s-a deteriorat.
Robotul continu s primeasc
instruciuni, dar le interpreteaz
nu ntotdeauna corect. Fiecare
instruciune este un triplet de
numere (u,vx,vy) ntregi pozitive. Dac u > 90, atunci robotul
se deplaseaz cu vx dup axa Ox i cu vy dup axa Oy. Dac
u 90, robotul se deplaseaz pe un arc de msura u al cercului de centru (vx,vy) mpotriva micrii acelor de ceasornic.
Raza cercului este segmentul care unete robotul cu centrul
cercului.
S se scrie un program care, dup coordonatele iniiale
ale robotului i un set dat de instruciuni, determin punctul
final n care va fi poziionat acesta.
Date de intrare
Prima linie a fiierului de intrare conine dou numere
ntregi coordonatele iniiale ale robotului. Urmtoarele
linii conin cte o instruciune, format din trei numere
ntregi, separate prin spaiu.
Date de ieire
Unica linie a fiierul de ieire va conine dou numere x
i y, separate prin spaiu, coordonatele finale ale robotului, indicate cu cel puin 3 cifre dup virgul.
Exemplu





date.in
3 2
130 4 1
45 1 7
91 0 3
60 0 6

date.out
-0.653 15.697

50

Copie autorizata pentru .campion

Rezolvare
program p02;
const pi=3.141592;
type point=record
x,y : real;
end;
var P: point;
alfa,xn,yn:real;
procedure move(var P:point; vx,vy:real);
begin
P.x:=P.x+vx;
P.y:=P.y+vy;
end;
procedure rotate (var P:point; u,vx,vy:real);
var old:point;
begin
old:=P;
P.x:=vx+(old.x-vx)*cos(u*pi/180)(old.y-vy)*sin(u*pi/180);
P.y:=vy +(old.x-vx)*sin(u*pi/180)+
(old.y-vy)*cos(u*pi/180);
end;
begin
assign(input,data.in); reset(input);
assign(output,data.out); rewrite(output);
readln(P.x,P.y);
while not eof do
begin
readln(alfa,xn,yn);
if alfa>90 then move(P,xn,yn)
else rotate(P,alfa,xn,yn);
end;
writeln(P.x:10:3, ,P.y:10:3);
close(input); close(output);
end.

51

Copie autorizata pentru .campion

6.3. Piatra

... i unde nu pornete stnca la vale, sltnd tot mai sus de


un stat de om; i trece prin gardul i prin tinda Irinuci, pe
la capre, i se duce drept n Bistria, de clocotea apa!
Ion Creang. Amintiri din copilrie

Piatra pornit de Ion Creang se rostogolea n linie


dreapt, drmnd totul n calea sa. Casa Irinuci are
muli perei, unii nimerind n calea pietrei. Fiind date
coordonatele a dou puncte prin care trece piatra i
extremitile segmentelor care descriu baza pereilor casei, s se determine ci perei vor fi drmai de piatra
n cdere. Peretele atins ntr-un punct extrem rmne ntreg.
S se scrie un program care determin numrul de
perei drmai de piatr.
Date de intrare
Fiierul de intrare date.in conine N (N < 1000) linii a
cte patru numere ntregi. Prima linie conine descrierea
a dou puncte prin care trece piatra, n forma x1, y1, x2, y2
(|xi, yi|<500). Urmtoarele N-1 linii conin descrierea
coordonatelor extremitilor bazelor pereilor, n aceeai
consecutivitate, cu aceleai restricii de valori.
Date de ieire
Unica linie a fiierul de ieire date.out va conine un
numr ntreg numrul de perei drmai de piatr.

52

Exemplu

date.in
2 1 9 14
2 4 1 8
1 12 3 9
4 14 6 11
7 14 9 10
9 14 7 16
6 10 8 8
3 6 6 6
4 2 4 5
11 10 12 14
8 6 10 8
12 8 14 4

Copie autorizata pentru .campion


date.out
4

Rezolvare
program p03;
type point=record
x,y: real;
end;
segment=record
e1,e2: point; end;
var g: array[1..1000] of segment;
l: segment;
n,i,k: integer;
function sarrus(p1,p2,p3:point): real;
begin
sarrus:=p1.x*p2.y+p2.x*p3.y+p1.y*p3.x
-p3.x*p2.y-p3.y*p1.x-p1.y*p2.x;
end;

begin
assign(input, date.in); reset(input); n:=0;
readln(l.e1.x,l.e1.y,l.e2.x,l.e2.y);
while not eof do
begin
inc(n); readln( g[n].e1.x,
g[n].e1.y,g[n].e2.x,g[n].e2.y);
end;
k:=0;
for i:=1 to n do
if
sarrus(l.e1,l.e2,g[i].e1)*sarrus(l.e1,l.e2,g[i].e2) < 0
then inc(k);
assign(output, date.out); rewrite(output);
writeln(k); close(input); close(output);
end.
53

Copie autorizata pentru .campion

6.4. Carcasa

Fie o carcas avnd forma


unui poligon simplu. Pentru
a fi poziionat vertical pe o
suprafa plan, carcasa trebuie
s aib centrul de mas situat
strict ntre 2 puncte de contact
cu suprafaa. Centrul de mas
este ntotdeauna un punct interior al carcasei i nu coincide cu nici un vrf al ei.
S se scrie un program care va determina numrul
poziiilor n care poate fi stabilizat vertical carcasa.
Date de intrare
Prima linie a fiierului de intrare date.in conine trei
numere ntregi, separate prin spaiu: N numrul de
vrfuri ale carcasei i xc, yc coordonatele centrului de
mas.
Urmeaz N linii ce conin cte dou numere ntregi xi, yi
(1000 xi , yi 1000), separate prin spaiu, coordonatele
vrfurilor poligonului n ordinea parcurgerii lor.
Date de ieire
Fiierul de ieire date.out va conine un singur numr
ntreg numrul de poziii n care poate fi stabilizat vertical carcasa.
Restricii

3 N 1000
1000 xc , yc 1000

54

Exemplu

Copie autorizata pentru .campion

date.in date.out
10 6 16 3
3 14
13 4
23 14
33 4
33 14
23 24
13 14
3 24
-7 14
-7 4

Rezolvare
Deoarece carcasa se sprijin pe careva puncte extreme ale poligonului, pro
blema poate fi divizat n dou subpro
bleme relativ simple:

1) determinarea nfurtoarei
convexe a vrfurilor poligonului;
2) verificarea dac un triunghi are un unghi obtuz.

Prima subproblem este rezolvat cu ajutorul algoritmului descris anterior ( 3.2).


Dup determinarea nfurtoarei
convexe, problema poate fi reformulat
n felul urmtor:
Fie un poligon convex P i un punct
interior c, unit prin linii drepte cu vrfurile poligonului. n
cte dintre triunghiurile formate nlimea construit din
punctul c se proiecteaz ntr-un punct interior al laturii
poligonului care aparine triunghiului?
Evident, nlimea construit din c se proiecteaz pe
latur dac niciunul dintre unghiurile alturate laturii poligonului nu este obtuz. Verificarea unghiurilor se realizeaz
elementar cu ajutorul teoremei cosinusurilor. Complexitatea etapei este liniar dup numrul de vrfuri.
55

Copie autorizata pentru .campion

6.5. Turnuri

Bitlanda este o ar care se extinde permanent, lini


ar. Frontiera rii reprezint o linie frnt nchis, fr
autointersecii. Pentru a apra frontierele sale, dup fiecare extindere, n noile puncte extreme ale frontierei se
construiesc turnuri de veghe. Exist N turnuri de veghe,
date prin coordonatele lor (xi , yi) numere ntregi. Regele
Bitlandei, Bytezar, a decis sa trimit la vatr garnizoanele
turnurilor care nu se mai afl la hotarele rii.
S se scrie un program care va determina cte turnuri
vor fi lipsite de garnizoane.
Date de intrare
Prima linie a fiierului de intrare conine un numr
ntreg: N (1 N 10000) numrul de turnuri de veghe
n Bitlanda.
Urmeaz N linii ce conin cte dou numere ntregi xi , yi
(1000 xi , yi 1000), separate prin spaiu, coordonatele
turnurilor de veghe.
Date de ieire
Fiierul de ieire va conine un numr ntreg numrul
de turnuri care pot fi lipsite de garnizoane.
Exemplu
turn.in turn.out
10 5
2 1
3 4
6 3
6 6
8 5
10 3
11 7
12 6
9 11
15 8

56

6.6. Atac

Copie autorizata pentru .campion

Agenia Spaial a planetei Bitterra (ASB) a recepionat un


roi meteoritic, care se apropie de planet. Fiecare stat de pe
Bitterra a fost anunat despre pericol i a primit lista punctelor
de cdere a meteoriilor, calculate de ASB. Serviciile pentru
situaii excepionale ale fiecrui stat urmeaz s determine
ci meteorii vor cdea pe teritoriul rii. Frontiera oricrui
stat de pe Bitterra este un poligon convex; meteoriii sunt punctiformi. Punctele de pe frontier nu se consider aparinnd
statului. Frontiera poate conine mai multe vrfuri consecutive
coliniare.
S se scrie un program care va determina numrul de
meteorii ce cad pe teritoriul unui stat dat.
Date de intrare
Prima linie a fiierului de intrare atac.in conine numrul
n numrul de vrfuri ale poligonului care descrie frontiera
unui stat. Urmtoarele n linii conin descrierea consecutiv a
vrfurilor frontierei: fiecare linie va conine cte o pereche de
numere separate prin spaiu coordonatele unui vrf. Urmeaz
o linie care conine un numr ntreg m numrul de meteorii,
apoi m linii, care conin cte dou numere, separate prin spaiu,
coordonatele punctelor de cdere a meteoriilor.
Date de ieire
Fiierul de ieire atac.out va conine un singur numr ntreg cel al meteoriilor care cad pe teritoriul statului dat.
Restricii
1. Coordonatele vrfurilor poligonului i ale punctelor de
cdere a meteoriilor sunt numere ntregi din intervalul
[-1000000, 1000000].
2. 3 n 20000.
3. 2 m 20000.
57

Copie autorizata pentru .campion

Exemplu

atac.in atac.out Explicaie


4 2
2 4
8 4
6 8
4 6
4
3 5
4 7
5 5
6 7

Rezolvare
Formularea abstract a problemei este urmtoarea:
Fie n plan un poligon convex P cu n vrfuri. n acelai
plan este dat o mulime M din m puncte. Se cere s se
determine cte puncte din M aparin interiorului P.
Rezolvarea se divide n cteva etape.
1. Se determin un punct interior
al poligonului de coordonate
(xcm , ycm) (de exemplu, centrul
de mas).
Fiind date coordonatele (xi , yi),
i = 1, n , ale vrfurilor poligonului
P, coordonatele centrului de mas
pot fi calculate dup formula:
n

xcm =

x
i =1

ycm =

y
i =1

2. Fiind dat un punct interior (xcm , ycm) al poligonului,


se calculeaz unghiurile pe care le formeaz cu axa Ox
semidreptele duse din acesta prin vrfurile (cx , cy).
58

Copie autorizata pentru .campion


function angle(cx,cy:real): real;
begin
sinus:=(cy -ycm)/ sqrt(sqr(cy-ycm)+sqr(cx-xcm));
cosinus:= (cx -xcm)/ sqrt(sqr(cy-ycm)+sqr(cx-xcm));
if cosinus=0 then
if sinus>0 then angle:= pi/2
else if sinus<0 then angle:=3*pi/2
else begin
if (sinus>0) and (cosinus>0)
then angle:=arctan(sinus/cosinus);
if (sinus>0) and (cosinus<0)
then angle:=pi-arctan(abs(sinus/cosinus));
if (sinus<=0)and (cosinus<0)
then angle:=pi+arctan(abs(sinus/cosinus));
if (sinus<=0) and (cosinus>0)
then angle:=2*pi-arctan(abs(sinus/cosinus));
end;
end;

3. Pentru un punct dat al


mulimii M se calculeaz unghiul format de semidreapta
determinat de acesta i centrul de mas al poligonului cu
axa Ox. Se folosete aceeai
funcie de la etapa 2.
alfa:=angle(b[i].x,b[i].y)

4. Se determin latura poligonului intersectat de semidreapta determinat la pasul 3. Pentru optimizarea


acestui pas se folosete cutarea binar.
k:=1; {determinarea vrfului cu unghi maxim}
while (a[k].u<=a[k+1].u) and (k<n) do k:=k+1;
{divizarea binara}
if (alfa < a[k+1].u) or (alfa>a[k].u)
59

Copie autorizata pentru .campion


then begin st:=k; dr:=k+1; end
else begin
if (alfa < a[1].u)
then begin st:=k+1; dr:=n+1; end
else begin st:=1; dr:=k;
end;
repeat
mj:=(st + dr) div 2;
if a[mj].u >alfa then dr:=mj else st:=mj
until dr=st+1;
end;

5. Se determin poziia centrului de mas i a punctului curent al mulimii M fa de latura determinat.


Dac sunt de aceeai parte, punctul curent este
n interior. Pentru determinarea poziiei se
folosete

semnul

determinantului

x1
x2
x3

y1 1
y2 1 ,
y3 1

unde (x1, y1), (x2, y2) sunt coordonatele vrfurilor care


determin latura, iar (x3, y3) coordonatele punctului
cercetat (respectiv coordonatele centrului de mas).

q:=semn(a[st].x,a[st].y,a[dr].x,a[dr].y,b[i].x,b[i].y);
p:=semn(a[st].x,a[st].y,a[dr].x,a[dr].y,xcm,ycm);
if p*q>0 then inc(s);

60

6.7. Evadare

Copie autorizata pentru .campion

Un grup de pinguini a decis s evadeze din grdina


zoologic. n acest scop ei au spat un tunel liniar. Din
nefericire, zidul grdinii zoologice formeaz un poligon
simplu cu N (3N10000) laturi, astfel nct, ieind din
tunel, pinguinii nu pot afirma cu certitudine dac se afl
n interiorul grdinii zoologice sau n afara ei.
S se scrie un program care, dup coordonatele punctelor extreme ale tunelului i coordonatele vrfurilor poligonului ce stabilesc perimetrul grdinii zoologice, va determina dac evadarea s-a soldat cu succes sau nu.
Date de intrare
Prima linie a fiierului de intrare evadare.in conine
patru numere ntregi, separate prin spaiu, coordonatele
punctelor extreme ale tunelului. Urmtoarele linii conin
descrierea consecutiv a vrfurilor zidului: fiecare linie va
conine cte o pereche de numere, separate prin spaiu,
coordonatele unui vrf.
Date de ieire
Fiierul de ieire evadare.out va conine un singur cuvnt: DA n cazul n care punctul final al tunelului este
n afara grdinii zoologice; NU n caz contrar.
Restricii
Coordonatele vrfurilor poligonului i ale punctelor
extreme ale tunelului sunt numere ntregi din intervalul
[-1000, 1000].

61

Copie autorizata pentru .campion

Exemplu

evadare.in evadare.out explicaie


5 3 7 7 DA
1 2
2 6
6 4
6 7
7 5
10 4
7 2
3 1

6.8. Arcai
Secretul victoriilor faimo
sului comandant de oti MegaFlop este strategia lui de
alegere a poziiei arcailor pe
cmpul de lupt. Cmpul are
forma unui poligon simplu i
e nconjurat de pduri. MegaFlop plaseaz arcaii doar pe
poziii din care este vzut tot
cmpul de lupt. Se consider
c arcaii vd tot cmpul, dac din orice punct care aparine
poziiei lor de tragere se poate trage cu sgeata n orice alt
punct al cmpului. Traiectoria sgeii este liniar. Nimerind
n pdure, sgeata se pierde. Pentru tragere, fiecare arca
are nevoie de o unitate de suprafa. Astfel, numrul ma
xim de arcai care pot fi plasai pe poziii este determinat
de aria poligonului din care este vzut toat cmpia.
S se scrie un program care determin numrul maxim
de arcai care pot fi plasai pe poziii de tragere n cmpul
de lupt.
62

Copie autorizata pentru .campion

Date de intrare
Fiierul de intrare arcas.in va conine pe prima linie un
numr ntreg N numrul de vrfuri ale poligonului simplu care descrie perimetrul cmpului de lupt. Urmeaz N
linii care conin coordonatele vrfurilor poligonului, parcurse n sensul micrii acelor de ceasornic, cte un vrf
pe linie. Linia i+1 conine dou numere ntregi xi, yi,
separate prin spaiu, coordonatele vrfului i.
Date de ieire
Fiierul de ieire arcas.out va conine un singur numr
ntreg numrul maxim de arcai care pot fi plasai pe
poziii.
Restricii

3 N 1000
0 < xi, yi 10000

Exemplu

arcas.in arcas.out
9 11
2 5
3 6
2 7
4 7
6 9
8 6
7 2
5 4
3 4

Rezolvare
program p68;
type
lat=record x,y:real; end;
pol=array[0..1001] of lat;

63

Copie autorizata pentru .campion


var
nuc,camp:pol;
i,nnuc,ncamp:integer;
xint,yint:real;

procedure init;
var square : array[1..5,1..2] of integer;
i: integer;
begin
{initializare nucleu}
nuc[1].x:=0; nuc[1].y:=0;
nuc[2].x:=0; nuc[2].y:=10001;
nuc[3].x:=10001; nuc[3].y:=10001;
nuc[4].x:=10001; nuc[4].y:= 0;
nuc[5].x:=nuc[1].x; nuc[5].y:= nuc[1].y;
nnuc:=4;
{ si initializare poligon}
readln(ncamp);
for i:=1 to ncamp do readln(camp[i].x,camp[i].y);
camp[ncamp+1].x:=camp[1].x;camp[ncamp+1].y:=camp[1].y;
end;

function intersect
(al,bl,cl,ad,bd,cd:real;i,j:integer): boolean;
{determin intersecia dreptei i laturii
+ coordonate punctului de intersecie}
begin
{1. dreapta i latura sunt paralele}
if Ad*Bl=Bd*Al then begin intersect:=false; exit; end;
{2. dreapta intersecteaz 2 laturi adiacente n punct
extrem}
if (camp[j+1].x=nuc[i].x) and (camp[j+1].y=nuc[i].y)
then begin
intersect:=true; xint:=nuc[i].x; yint:=nuc[i].y;
exit;
end;
if (camp[j].x=nuc[i+1].x) and (camp[j].y=nuc[i+1].y)
then begin
intersect:=true; xint:=nuc[i+1].x;
yint:=nuc[i+1].y; exit;
end;
64

Copie autorizata pentru .campion


{3. Dreapta i latura nu sunt paralele}
if (Ad*Bl<>Bd*Al) then
if Al<>0 then begin
yint:=(Ad*Cl-Cd*Al)/(Bd*Al-Ad*Bl);
xint:=(-Bl*yint-Cl)/Al;
end
else
begin yint:=-Cl/Bl;
xint:=(-Bd*yint-Cd)/Ad;
end;
if (((xint>=nuc[i].x) and (xint<=nuc[i+1].x))
or ((xint>=nuc[i+1].x) and (xint<=nuc[i].x)))
and(((yint>=nuc[i].y) and (yint<=nuc[i+1].y))
or ((yint>=nuc[i+1].y) and (yint<=nuc[i].y)))
then intersect:=true else intersect:=false;
end;

function sarrus(a,b,c:lat):real;
begin
sarrus:=a.x*b.y+b.x*c.y+a.y*c.x-c.x*b.y-b.x*a.y-c.y*a.x;
end;
procedure cut(j:integer);

{ Proceseaz latura j a poligonului P}


var
al,bl,cl,ad,bd,cd:real;
inter: array[1..4] of lat;
index: array[1..4] of integer;
k,ii,i,nr:integer;
copy: pol;
begin
Ad:=camp[j+1].y - camp[j].y; Bd:=camp[j].x-camp[j+1].x;
Cd:=camp[j+1].x*camp[j].y-camp[j].x*camp[j+1].y;
nr:=0;
for i:=1 to nnuc do
begin
Al:=nuc[i+1].y -nuc[i].y; Bl:=nuc[i].x-nuc[i+1].x;
Cl:=nuc[i+1].x*nuc[i].y-nuc[i].x*nuc[i+1].y;
if intersect(al,bl,cl,ad,bd,cd,i,j) then

65

Copie autorizata pentru .campion


begin
nr:=nr+1;
inter[nr].x:=xint;
inter[nr].y:=yint;
index[nr]:=i;
end;
end;
if nr>=2 then
begin
if sarrus(camp[j],camp[j+1],nuc[index[1]])>=0
then
begin
ii:=1;
copy[1].x:=inter[1].x;

copy[1].y:=inter[1].y;
for k:=index[1]+1 to index[2] do
begin
inc(ii); copy[ii]:=nuc[k];
end;
inc(ii); copy[ii].x:=inter[2].x;
copy[ii].y:=inter[2].y;
nnuc:=ii;
inc(ii); copy[ii].x:=inter[1].x;
copy[ii].y:=inter[1].y;
end
else
begin
ii:=0;
for k:=1 to index[1] do
begin inc(ii); copy[ii]:=nuc[k]; end;
inc(ii);
copy[ii].x:=inter[1].x;copy[ii].y:=inter[1].y;
inc(ii);
copy[ii].x:=inter[2].x;copy[ii].y:=inter[2].y;
for k:=index[2]+1 to nnuc do
begin inc(ii); copy[ii]:=nuc[k]; end;
nnuc:=ii; inc(ii); copy[ii]:=nuc[1]
end;
nuc:=copy;
end

66

Copie autorizata pentru .campion


else
if sarrus(camp[j],camp[j+1],nuc[1])>=0 then
begin
writeln(0); close(output); halt;
end;
end;
function area(a:pol;n:integer):real;
{aria poligonului simplu}
var s:real;
i:integer;
begin
s:=0;
for i:=1 to n do
s:=s+(a[i+1].x-a[i].x)*(a[i+1].y+a[i].y)/2;
area:=s;
end;
{programul principal}
begin
assign(input,arcas.in);
reset(input);
assign(output,arcas.out);
rewrite(output);
init;
for i:=1 to ncamp do
cut(i);
writeln(area(nuc,nnuc));
close(input);
close(output);
end.

67

Copie autorizata pentru .campion

6.9. Cetate

Arheologii din Bitlanda n timpul


spturilor au descoperit nite pietre
aezate oarecum straniu. Ei au ajuns
la concluzia ca acestea formeaz fragmente ale unui zid circular, care nconjura o cetate veche.
Pentru a proteja de turiti i de
curioi fragmentele descoperite, arheo
logii au decis s le nconjoare cu un gard din plas metalic.
Deoarece este destul de complicat i incomod de a nconjura
fiecare fragment, s-a luat decizia de a mprejmui toate fragmentele mpreun.
S se scrie un program care s determine lungimea minim
a plasei necesare pentru a ngrdi fragmentele zidului.
Date de intrare
Prima linie a fiierului de intrare conine dou numere:
n (1n180) numrul fragmentelor de zid; r (1r100)
raza zidului. Urmeaz n perechi de numere ntregi, care
descriu fragmentele de zid: ai, bi msura unghiurilor
(n grade) care descriu nceputul i sfritul fragmentului. Unghiurile se msoar ncepnd cu direcia nord de
la centrul cetii, n sens opus micrii acelor de ceasornic
(0 ai; bi < 360, ai bi). Fiecare fragment este descris
la fel mpotriva direciei de micare a acelor de ceasornic.
Fragmentele de zid nu au puncte comune.
Date de ieire
Fiierul de ieire va conine lungimea minim a plasei
necesare, cu trei cifre dup virgul.
Exemplu
cetate.in cetate.out
2 10 61.888
330 30
90 270

68

6.10. Druizi

Copie autorizata pentru .campion

Ruinele din Stonehenge se af


l ntr-un loc special, unde se
intersecteaz M linii energetice
ale Pmntului. Liniile energe
tice mpart cmpia Stonehenge
n sectoare. n fiecare an, n cea
mai scurt zi a anului, N druizi
se adun n cmpie pentru un
ritual, ce asigur o road bogat
pentru anul urmtor. Pentru succesul ritualului este necesar
ca n fiecare sector al cmpiei, delimitat de liniile energetice,
s se afle nu mai mult dect un druid. Cmpia are forma unui
ptrat cu centrul n originea sistemului de coordonate i care
are lungimea laturii 2 L. Liniile energetice sunt linii drepte.
Druizii sunt punctiformi i nu se pot afla pe liniile energetice.
S se scrie un program care determin dac exist sectoare ale cmpiei n care se afl 2 sau mai muli druizi.
Date de intrare
Fiierul de intrare conine cteva (cel mult 5) seturi de
date, separate prin cte o linie ce conine semnul #.
Prima linie a fiecrui set de date conine numerele N, M i
L (1 N 1000, 0 M 1000, 1 L 2000).
Urmeaz N linii ce conin cte dou numere ntregi xi, yi
coordonatele druizilor. Toi druizii se afl n interiorul cm
piei, oricare doi druizi nu coincid.
Urmtoarele M linii ale setului de date conin cte un
triplet de numere ntregi ai, bi, ci. Numerele corespund
coeficienilor ecuaiei Ai x + Bi y + Ci = 0, care descrie linia
energetic i. Niciun druid nu se afl pe o careva linie. Oricare
dou linii nu coincid. Valorile ai, bi, ci nu depesc 10000
dup modul.
69

Copie autorizata pentru .campion

Date de ieire
Fiierul de ieire va conine pentru fiecare set de date
cuvntul YES, dac exist cel puin un sector n care se
afl doi sau mai muli druizi, NO, n caz contrar. Fiecare
rspuns se va scrie ntr-o linie aparte, n ordinea apariiei
seturilor de date n fiierul de intrare.
Exemplu

druizi.in druizi.out
3 2 3 YES
2 2 NO
1 -1
-2 0
1 1 -1
0 1 -1
#
1 0 100
0 0

Rezolvare
Pentru implementare vor fi definite tipurile i structurile:
type pt=record x,y,a:real; T:char;
end;
dr=array[1..3003] of pt;
var
d:dr;
n,m,i:integer;
int,xint,r,a,b,c,ae,be,ce,de,
l1a,l2a,l1b,l2b,l1c,l2c: real;

Pentru citirea i preprocesarea datelor va fi utilizat


procedura readdata:
procedure readdata;
begin
readln(n,m,r);
for i:=1 to n do
begin readln(d[i].x,d[i].y);
70

d[i].t:=L; end;

Copie autorizata pentru .campion


for i:=1 to m do
begin
readln(a,b,c);
if i=1 then begin l1a:=a; l1b:=b; l1c:=c; end;
if i=2 then begin l2a:=a; l2b:=b; l2c:=c; end;
ae:=b*b+a*a;
be:=2*b*c;
ce:=c*c-a*a*2*r*r;
de:=be*be-4*ae*ce;
if a<>0 then begin
inc(n);
d[n].y:=(-be-sqrt(de))/2/ae;
d[n].x:=(-b*d[n].y-c)/a;
d[n].t:=D;
inc(n);
d[n].y:=(-be+sqrt(de))/2/ae;
d[n].x:=(-b*d[n].y-c)/a;
d[n].t:=D;
end
else begin
inc(n);
d[n].y:=-c/b;
d[n].x:=sqrt(2*r*r-c*c/b/b);
d[n].t:=D;
inc(n);
d[n].y:=d[n-1].y;
d[n].x:=-d[n-1].x;
d[n].t:=D;
end;
end;
end; {readdata}

n rezolvare vor fi parcurse urmtoarele etape:


1. Toate liniile se intersecteaz ntr-un punct, care trebuie
determinat. Dac numrul de linii este 0 sau 1, sunt
cteva cazuri elementare, care se cerceteaz aparte.
Dac numrul de linii este mai mare sau egal cu doi,
atunci se folosesc oricare dou linii pentru a determina
coordonatele punctului de intersecie.
71

Copie autorizata pentru .campion

2. Druizii se afl n interiorul


ptratului cu latura 2L i
centul n originea sistemului de coordonate. Ei se afl
i n interiorul cercului de
raz 2L i centrul n ori
ginea sistemului de coordonate. Pentru fiecare din liniile energetice se determin
punctele ei de intersecie cu
cercul de raz 2L i centrul n originea sistemului
de coordonate. Aceste puncte se marcheaz aparinnd
dreptelor (D) de separare a sectoarelor.
3. Originea sistemului de
coordonate se deplaseaz n
punctul de intersecie a dreptelor (liniilor energetice). Apoi se
trece la coordonatele polare
pentru punctele ce reprezint
druizii i interseciile liniilor
energetice cu cercul (realizare
procedura movecenter).
procedure movecenter;
begin
{se determin punctul de intersectie al dreptelor}
if l1a<>0 then
begin yint:=(l1c*l2a-l1a*l2c)/(l2b*l1a-l2a*l1b);
xint:=(-l1b*yint-l1c)/l1a;
end
else begin yint:=-l1c/l1b;
xint:=(-l2b*yint-l2c)/l2a;
end;
72

Copie autorizata pentru .campion


for i:=1 to n do
begin
{se transfer originea..}
d[i].x:=d[i].x - xint; d[i].y:=d[i].y - yint;
{ ... si se determin coordonatele polare - unghiul!}
if d[i].x<>0 then
begin
d[i].a:=180/pi*arctan(abs(d[i].y/d[i].x));
if (d[i].x<0) and (d[i].y>0) then d[i].a:=180-d[i].a;
if (d[i].x<0) and (d[i].y<=0) then d[i].a:=d[i].a+180;
if (d[i].x>0) and (d[i].y<0) then d[i].a:=360-d[i].a;
end
else begin if d[i].y> 0 then d[i].a:=90;
if d[i].y<0 then d[i].a:=270;
end;
end
end; {movecenter}

4. Se sorteaz sistemul de puncte pi dup


creterea
msurii unghiului format de fiecare vector Opi cu axa

Ox.

5. Dac dup sortare exist cel puin dou puncte vecine,


reprezentnd druizi, rezult existena unui sector al
cmpiei cu aceeai proprietate.
procedure solve;
var vec: boolean;
begin
{cazurile elementare...}
if

if

if

((m=0) and (n=1)) or ( (m=1) and (n=3))


then writeln(NO);
((m=0) and (n>1)) or ((m=1) and (n>4))
then writeln(YES);
(m=1) and (n=4) then
begin
73

Copie autorizata pentru .campion


{se determin pozitia druizilor fata de dreapta}
if sarrus(d[3],d[4],d[1])*sarrus(d[3],d[4],d[2]) < 0
then writeln(NO) else writeln(YES);
end;
if m>=2 then
begin
{... si cazul general}
movecenter;
qsort(d,1,n);
vec:=FALSE;
for i:=1 to n-1 do
if (d[i].t=L) and (d[i+1].t=L)
then vec:=TRUE;
if vec then writeln(YES) else writeln(NO);
end;
end; {solve}

74

Copie autorizata pentru .campion

Notaii

p1 p2 segment orientat (vector) cu


originea n punctul p1
S = { p1 ,..., pN } mulimea S, cu elementele p1, ..., pN
|S|

cardinalul mulimii S

i incrementarea valorii i cu 1
k m variabilei k i se atribuie valoarea
variabilei m
[a, b]

interval cu extremitile a, b

abc triunghi cu vrfurile a, b, c


DV(S) diagrama Voronoi pentru mulimea S
T(S) triangularizarea mulimii S
Q(S) nfurtoarea convex a mulimii S
A B din A rezult B
A B A este echivalent cu B
x X , ( x X ) x aparine (nu aparine) mulimii X

{x X : Q}

submulimea elementelor x din X, care


satisfac condiia Q

A B A se conine n B (A este submulime


a mulimii B)
qsort(A,n)

apel al procedurii pentru sortarea


structurii de date A din n elemente

75

Copie autorizata pentru .campion

Bibliografie

1. Ammeraal, Leen. Programming Principles in Computer


Graphics. John Wiley and Sons, 1986.
2. Ammeraal, Leen. Computer Graphics for the IBM PC. John
Wiley and Sons, 1986.
3. Cerchez, Emanuela. Programarea n limbajul C/C++ pentru liceu. Vol III. Iai: Polirom, 2007.
4. Cormen, Thomas. Introducere n algoritmi. Cluj: Agora.
5. Foley, James; Andries, Van Dam. Fundamentals of Interactive Computer Graphics. Addison-Wesley Publishing, 1984.
6. Giumale, Cristian. Introducere n analiza algoritmilor. Iai:
Polirom, 2004.
7. Sedgewick, Th. Algorithms in C. Addison Wesley, 2001.
8. Williamson, Gill. Combinatorics for Computer Science. New
York: Dover publications, 2002.
9. , .
++. : , 1997.
10. , . . : ,
1986.
11. , . .
. : , 2001.
12. , . .
. : , 1985.
13. , .; , .
. . : , 1989.

76

S-ar putea să vă placă și