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: Coperta: Tatiana Rusu 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 1.1. Deplasri i rotaii 1.2. Coordonate polare 1.3. Implementri 2. Intersecii 2.1. Intersecia dreptelor 2.2. Intersecia dreptei cu un segment 2.3. Intersecia segmentelor 3. nfurtoarea convex 3.1. Algoritmul elementar 3.2. Algoritmul Graham 4. Triangularizri 4.1. Un algoritm greedy pentru mulimi de puncte 4.2. Triangularizarea poligoanelor convexe 4.3. Triangularizarea poligoanelor simple 5. Apropiere i apartenen 5.1. Cea mai apropiat pereche de puncte 5.2. Apartenena punctului la un domeniu 5.3. Poligonul i diagrama Voronoi 5.4. Nuclee 5 7 7 9 10 12 12 14 16 17 17 20 26 26 28 29 31 31 35 39 44

Copie autorizata pentru .campion

6. Probleme geometrice de concurs 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 Notaii Bibliografie

48 48 50 52 54 56 57 61 62 68 69 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 computaional 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:

Modificarea combinat a coordonatelor cu a dup axa Ox i b dup Oy va fi dat de sistemul:

x = x, y = y + b.

Fig. 1.1. Rotaia punctului cu un unghi

x = x + a , y = y + b.

coordonate (fig. 1.1).

a punctului (punctelor) fa de originea sistemului de


7

Urmtorul tip de transformare este rotaia cu un unghi

Copie autorizata pentru .campion

n unele cazuri, operaia poate fi realizat invers: prin rotaia originii sistemului 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 .

ordonate ia forma:

a unui punct arbitrar n jurul originii sistemului de co x = x cos y sin , y = x sin + y cos .

Astfel, sistemul de ecuaii pentru rotaia cu un unghi

Copie autorizata pentru .campion

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 unghiul format de vecto Fig. 1.3. Coordonatele polare ale rul Op cu axa Ox (fig. 1.3). punctului de coordonate carteziene
(x, y) 9

Copie autorizata pentru .campion

Trecerea de la coordonatele carteziene (x, y) la cele polare este determinat de urmtoarele formule [1, p. 77]:
x arctan y x + arctan y = 2 3 2 y>0 y<0 x = 0, y > 0 x = 0, y < 0

r= x +y ,

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

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;

Copie autorizata pentru .campion

La fel de simpl este i o posibil implementare a rotaiei 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 problemelor de geometrie computaional 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

ce trece prin aceste dou puncte este:

Copie autorizata pentru .campion

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. A = y2 y1 ,

(2.2)

Din (2.2) rezult formulele de calcul pentru coeficienii ecuaiei generale:

B = x1 x2 , C = x2 y1 x1 y2 .
Determinarea punctului de intersecie a dou drepte

(2.3)

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

Se observ c n cazul interseciei dreptei l i a segmentului s, extremitile segmentului sunt poziionate de pri diferite fa de vectorul p2 p1 . Dac obiectele cercetate nu se intersecteaz, atunci ambele extremiti segmentuale lui se afl de aceeai parte a vectorului p2 p1 (fig. 2.2).

Copie autorizata pentru .campion

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]:

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

x2 = x1 x3

y2 1 y1 1 . y3 1

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 intersecteaz (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 diferite). 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 nfurtoarei 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 analitice. 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 determinare 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, punctele 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: Pseudocod Pas 1 Pas 2

Fig. 3.2. Determinarea unui punct interior

CS
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

then

C C /{ p}

18

Apartenena punctului la un triunghi

Copie autorizata pentru .campion

Condiia p pi p j pk poate fi verificat prin determi narea poziiei punctului p fa de fiecare din vectorii pi p j , 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 genereaz un numr de operaii proporional cu N 4 , ceea ce de4 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 nfurtoarea 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 de puncte de abscis minim (fig. Fig. 3.3. Parcurgerea listei(punctele p conform algoritmului Graham , p2, 1 3.3). Acesta este un punct p3 marcheaz tripletul curent)
20

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 .

Copie autorizata pentru .campion

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 Pas 2 Pas 3 Se determin un punct interior z ,

z S.

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

Pas 4 Pas 5 Pas 6


2

Fiecare element al listei descrie un punct al mulimii S.

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 de vectorul pk pi , 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 sistemului de coordonate i a calculului coordonatelor polare. La baza variantei Andrew st urmtorul principiu: partea 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

Pseudocodul algoritmului are urmtoarea form: Pas 1 Pas 2

Copie autorizata pentru .campion

Se determin dou puncte extreme pmin , pmax S de abscis minim (respectiv maxim). 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. Se sorteaz Ssup, Sinf dup creterea abscisei.

Pas 3

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 .
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. Pas 5

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

scris prin extremitile sale:

Numrul total de laturi posibile pe punctele din S este N 2 2 . Fiecare latur poate fi cercetat ca un segment de-

Copie autorizata pentru .campion

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 (lungimea 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 Pas 2 m 0


for for j 1+i to N do Begin m Latura[m].l Latura[m].st Latura[m].fin End;

i 1 to N do

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

Pas 3
3

qsort(Latura,m);

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 Pas 5

k0

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

constant de operaii. Triangularizarea poligonului convex poate fi util pentru calculul ariei lui. Aria poligonului este egal cu suma ariilor triunghiurilor din triangularizare.

Copie autorizata pentru .campion

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 urmeaz s fie incluse n triangularizare indiferent de locul ocupat n lista distanelor. Verificarea primei condiii este echivalent cu verificarea 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 Pas 2
m

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 Pas 4

Pas 5

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

qsort(Latura,m);

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;

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;

Verificarea apartenenei unui punct la un poligon are o complexitate liniar fa de numrul N de laturi ale acestuia. Prin urmare, complexitatea pasului 5 i complexitatea 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* ) = min d ( si , s j ). 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 :

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;

Fig. 5.1. Cea mai apropiat pereche de puncte

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 apropiat pereche de puncte, poate fi folosit tehnologia 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 mulimile asamblate. Numrul de divizri consecutive ale mulimii 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

Fie la un nivel de divizare mulimea S, irul X al elementelor din S sortate dup abscisa x, irul Y cu elementele 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 cercetat 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 punctului 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

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 elementelor mulimea punctelor care pot Fig.se5.5. Numrul pot modifica con cutive Y care mbunti soluia. Pentru fie- distana minim nu depete 9 care element din Y se calculeaz 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) Y S, sort(Y)
If

{sortare dup x} {sortare dup y}

Procedure apr2p(S, X, Y) begin

S 4

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( then

then

end else return

return

Y [i], Y [i+j]) < distance ( Y [i], Y [i+j])

distana minim n S {calculat direct}


34

5.2. Apartenena punctului la un domeniu


Apartenena punctului la un poligon convex

Copie autorizata pentru .campion

Problema determinrii apartenenei 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 interior 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

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

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

5.3. Poligonul i diagrama Voronoi

Copie autorizata pentru .campion

O alt problem de apropiere n plan este problema determinrii poligonului Voronoi 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 mulimii 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 trece 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 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 j yi xi y 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, valoarea coeficientului C este: Aym Bxm. Odat ce este cunoscut ecuaia dreptei l, perpendiculare 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 ) = 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
j =1,.., N j i

2 yi + y j

diagonale (xmin, ymin), (xmax, ymax): xmin = min ( xi ) 1 , xmax = max ( xi ) + 1 ,


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

Copie autorizata pentru .campion

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


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, perpendiculare 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 necesare 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 determinare 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 nfurtoarea 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 convex. Pentru latura superioar 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 interseciile 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

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 modificarea 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 concatenare 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 concatenare. Laturile din DV(S1), situate integral n dreapta de lanul de concatenare, i laturile 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

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 soluiilor pariale, n cazul alegerii structurii de date adecvate7, 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
Fig. 5.15. Poligon simplu cu nucleu (partea colorat a poligonului)

6 7

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


44

O structur optim este lista bidirecional a laturilor.

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. Algoritmul pentru determinarea nucleului unui poligon simplu

Copie autorizata pentru .campion

Fig. 5.16. Poligon simplu fr nucleu

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 valorilor minime i maxime ale abscisei i ale ordonatei. n calitate de Q poate fi considerat dreptunghiul cu vrfurile ( 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

Pas 2

Procesarea laturii i

Copie autorizata pentru .campion

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 ) . b) Se determin Q {Q1 , Q2 } care se afl n dreapta vectorului pi pi +1 .
* * c) Q Q

Pas 3

Repetare

i < N then begin i goto pas 2 STOP Q este nucleul.


if
2

end

else

Complexitatea algoritmului este O ( N ) . Se prelucreaz 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.

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 instruciuni 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

Copie autorizata pentru .campion date.out 4

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

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.out 3

date.in 10 6 16 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, problema poate fi divizat n dou subprobleme 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, liniar. 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 10 2 1 3 4 6 3 6 6 8 5 10 3 11 7 12 6 9 11 15 8 turn.out 5

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:

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 faimosului 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 maxim 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

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
arcas.in 9 2 5 3 6 2 7 4 7 6 9 8 6 7 2 5 4 3 4 arcas.out 11

Copie autorizata pentru .campion

Exemplu

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

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);

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;

{ 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, arheologii 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 2 10 330 30 90 270 cetate.out 61.888

68

6.10. Druizi

Copie autorizata pentru .campion

Ruinele din Stonehenge se afl ntr-un loc special, unde se intersecteaz M linii energetice ale Pmntului. Liniile energetice 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 cmpiei, 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 3 2 3 2 2 1 -1 -2 0 1 1 -1 0 1 -1 # 1 0 100 0 0 druizi.out YES NO

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 originea 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 ((m=0) and (n=1)) or ( (m=1) and (n=3)) then writeln(NO); if ((m=0) and (n>1)) or ((m=1) and (n>4)) then writeln(YES); if (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 cardinalul mulimii S incrementarea valorii i cu 1 variabilei k i se atribuie valoarea variabilei m interval cu extremitile a, b triunghi cu vrfurile a, b, c diagrama Voronoi pentru mulimea S triangularizarea mulimii S nfurtoarea convex a mulimii S din A rezult B A este echivalent cu B submulimea elementelor x din X, care satisfac condiia Q A se conine n B (A este submulime a mulimii B) apel al procedurii pentru sortarea structurii de date A din n elemente

S = { p1 ,..., pN } mulimea S, cu elementele p1, ..., pN


|S|

i k m
[a, b]

abc DV(S) T(S) Q(S) A B A B

x X , ( x X ) x aparine (nu aparine) mulimii X

{x X : Q}
A B
qsort(A,n)

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