Documente Academic
Documente Profesional
Documente Cultură
Geometrie 5
Geometrie 5
Geometrie 5
Sergiu CORLAT
Chiinu, 2009
Cuprins
Introducere 5 7
7 9 10
1. Transformri de coordonate
1.1. Deplasri i rotaii 1.2. Coordonate polare 1.3. Implementri
12
12
16
17
17
26
28
Triangularizarea poligoanelor simple 29
31
6. Probleme geometrice de concurs 6.1. 6.2. 6.3. 6.4. 6.5. 6.6. 6.7. 6.8. 6.9. 6.10.
Notaii Bibliografie
Robot Robot II Piatra Carcasa Turnuri Atac Evadare Arcai Cetate Druizi
48 48 50 52 54 56 57 61 62 68 69 75 76
Introducere
Geometria computaional prezint 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 moder-ne, 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 concur-surilor de programare de cele mai diferite nivele. Prezenta lucrare este conceput ca un curs de iniiere n algoritmii de geometrie computaional pentru studenii facul-tilor de profil, pentru profesorii de informatic, precum i pen-tru 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, calcule ala complexitii. Cu toate c aparatul matematic necesar pentru rezolvarea problemelor de geometrie computaional este relativ simplu, implementarea acestora este nsoit de necesitatea cercetrii unui numr considerabil de cazuri
6
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 va 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 contri-buit la apariia acestei cri, n special colectivului Catedrei de Informatic i Tehnologii Informaionale a Universitii de Stat din Tiraspol.
Ianuarie 2009 Sergiu Corlat
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 siste-mului 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:
x = x + a, y = y + b.
Urmtorul tip de transformare este rotaia cu un unghi a pun-ctului (punctelor) fa de originea sistemului de coordonate (fig. 1.1). n unele cazuri, operaia poate fi realizat invers: prin rotaia originii
8
sistemului de coordonate fa de un punct (sau sistem de puncte) dat. n acest caz exist patru numere a,b,c,d, care permit de a trece univoc coordonatele ( x, y) n ( x, y) , utiliznd sistemul de ecuaii:
x = ax + by, (1.1) y = cx + dy. Pentru determinarea acestui cuadruplu de nume-re pot fi folosite punctele (1,0) i (0,1). Se observ c la rotaia cu un unghi punctul de co-ordonate (1,0) trece n pun-ctul (cos ,sin ) , iar (0, 1) n
( sin , cos ) (fig. 1.2). Dup nlocuirea acestor valori n calitate de coefi-cieni ai sistemului (1.1) se obine: x = a a = cos , y = c c = sin .
Analog:
x = b b = sin , y = d d = cos .
Astfel, sistemul de ecuaii pentru rotaia cu un unghi a unui punct arbitrar n jurul originii sistemului de coordonate ia forma: x = x cos y sin y = x sin + y cos
9
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, mai nti se transfer originea sistemului de coordonate n centrul de rotaie (deplasarea de coordonate), apoi se efectueaz rotaia n jurul noii origini a sistemului de coordonate:
uu u r
r = x2 + y 2 ,
x arctan y x + arctan y = 2 3 2
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 prin intermediul unui tablou unidimensional sau list alocat dinamic, cu elemente de tip point. Procedura de deplasare a coordonatelor cu valoarea vx dup axa Ox i vy dup Oy poate fi realizat n felul urmtor:
procedure move(var P:point; vx,vy:real); begin P.x:=P.x+vx; 11
P.y:=P.y+vy; end;
La fel de simpl este i o posibil implementare a rotaiei cu un unghi u fa de un punct de coordonate vx i 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;
12
2. Intersecii
n majoritatea problemelor 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 Fig. 2.1 Definirea dreptei (segmentului) prin drepte. dou puncte Metoda folosit pentru rezolvarea acestor subprob-leme este aceeai, cu dife-rene 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;
Din aceast ecuaie pot fi calculai coeficienii ecuaiei generale a dreptei: Ax + By + C = 0 . Efectund transformri elementare, din (2.1) se obine:
x( y 2 y1 ) + y ( x1 x2 )+ ( x2 y1 x1 y2 )= 0.
(2.2)
(2.3)
Determinarea punctului de intersecie a dou drepte Fie dreptele p i l, determinate respectiv de punctele p1
( x1 , y1 ) , p2 ( x2 , y2 ) i p3 ( x3 , y3 ) , p4 ( x4 , y4 )
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 . A C C1 A2 ysol = 1 2 , B2 A1 B1 A2 (2.4 a) B1 y sol C1 xsol = ; A1 b) Dac A1 = 0
ysol = xsol = C1 , B1 B2 ysol + C2 . A2
(2.4 b)
Cu ajutorul setului de formule (2.4) pot fi calculate coordonatele punctului de intersecie q ( xsol , ysol ) a dreptelor p i l.
15
Determinantul este pozitiv dac punctul s este situat n u uu uu r semiplanul drept fa de vectorul p2 p1 ; este nul, dac punctul s aparine dreptei determinate de acest vector, i negativ, dac s este plasat n semiplanul stng. O realizare posibil a funciei de calcul al determinantului este urmtoarea:
function sarrus(p1,p2,p3:point1): 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;
type point=record
16
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, tot segmentul aparine acesteia.
Coordonatele punctului de intersecie i n acest caz pot fi calculate folosind formulele 2.4.
17
3. nfurtoarea convex
Problema determinrii nf-urtoarei 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. Noiunea de nfurtoare Fig. 3.1. nfurtoarea convex a convex n plan este intuitiv unei mulimi de puncte simpl: pentru o mulime S de puncte ale planului, nfurtoarea convex Q( S ) este mulimea de vrfuri ale poligonului convex2 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).
S;
b) un punct p S nu este
un punct extrem dac i nu-mai dac, exist cel puin un triunghi, determinat de punctele pi , p j , pk S , ast-fel nct
p s se afle n interiorul
lui (fig 3.2). n baza acestor afirmaii, interior pun-ctele interioare ale mulimii se exclud prin cercetarea apartenenei fiecrui punct fiecrui triunghi generat de punctele mulimii S . Att pseudocodul, ct i implementarea algoritmului sunt extrem de simple: 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 p k
if
Fig. 3.2. Determinarea unui punct
p pi p j pk 3
then C C /{ p}
Condiia
p pi p j pk
sarrus(pi,pj,p), sarrus(pj,pk,p), sarrus(pk,pi,p), este aceAici i n continuare notaia p pi p j pk va specifica triunghiul n reuniune cu domeniul su interior 19
3
i j k lai, atunci . Prin urmare, verificarea dac un punct aparine interiorului unui 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
p p p p
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 reali-zat n cadrul funciei 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;
Afiarea coordonatelor punctelor, care formeaz nfur-toarea 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 mul-imi de puncte.
p2
fa de
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 . 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 6. 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 fiecrui punct p S , p z , apoi se sorteaz dup creterea (pentru punctele cu unghiuri egale 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: Se consider tripletul p1 p, p2 p[urm], p3 p2 [urm ]
Dac p2 e poziionat n semiplanul drept fa de vectorul
5 6
a) b)
c)
p p [urm ] , , atunci se efectueaz micarea nainte: 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 n cadrul verificrii poziiei p2 este mrginit de o constant. Modificarea Andrew Modificarea algoritmului are drept scop omiterea deter-minrii punctului intern z, deplasrii originii sistemului de coordonate, i a calculului coordonatelor polare. La baza variantei Andrew st urm-torul principiu: partea superi-oar (dup y ) a nfurtoarei convexe este bombat (n sus) pentru oricare 3 puncte Fig. 3.4. Construirea nfurtoarei conse-cutive ale sale, cea convexe. Modificarea Andrew inferioar bobmbat n jos (fig 3.4). Pseudocodul algoritmului are urmtoarea form: Pas 1 Se determin dou puncte pmin , pmax S de abscis minim (respectiv maxim).
23
Pas 2 Se separ S n Ssup i Sinf dup poziia punctelor fa de 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 consecutive pi , pi+1 , p i+ 2 S sup , pornind de la pmin . u u ur uuu Dac pi +1 este poziionat n stnga pi pi + 2 atunci se execut formeaz convexe. micarea partea nainte, superioar
altfel
u u u uu uuuu r
micarea
b. se verific toate tripletele consecutive pi , pi+1 , p i+ 2 S inf , pornind de la pmin . u u ur uuu Dac pi +1 este poziionat n dreapta pi pi + 2 , atunci se execut nainte, altfel micarea napoi. La atingerea pmax , punctele rmase n Sinf formeaz partea inferioar a nfurtoarei convexe. Pas 5 Q S inf S sup Mai jos este propus o realizare a acestui algoritm. Se presupune c punctele sunt date prin coordonatele lor numere ntregi. Sortarea este realizat de procedura qsort, care nu este descris aici, fiind considerat elementar. Poziia reciproc a punctelor este determinat de funcia sarrus, descris anterior. Structurile de date:
drag sus, jos n mulimea S - mulimile Ssup , Sinf - |S | 24
micarea
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; 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; 25
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 jos.
26
4. Triangularizri
Din punct de vedere geometric, triangularizarea T (S ) a mulimii de puncte S este o divizare a nfurtoarei convexe Q (S ) n fee din exact 3 muchii. Suplimentar, se vor respecta condiiile:
Prin urmare, verificarea interseciei muchiilor 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;
Pas 3 qsort(muchie,m);
28
N .
2
Numrul total de muchii generate este proporional cu Sortarea lor va necesita un numr de operaii
N 2 log( N ) . Complexitatea pasului 5 este proporional cu 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 .
Aici i n continuare prin poligon se va nelege conturul acestuia n reuniune cu domeniul lui interior. 29
4.2). Numrul diagonalelor este proporional cu N (numrul de vrfuri ale poligonului). Construcia unei diagonale necesit un numr constant de operaii. Triangularizarea poligonului convex poate fi util pentru calculul ariei lui. Aria poligonului este egal cu suma ariilor triunghiurilor din triangularizare.
a) aparine
interiorului
sau
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(Muchie[i],Triang[j]) then z true If NOT z then Begin x,y middle(Muchie[i]) if apart(x,y,P)then begin k; Triang[k] Muchie[i] end; End; End;
Verificarea apartenenei la domeniul interior al poligonului are o complexitate proporional cu numrul N de laturi n P . Prin urmare, nu influeneaz complexitatea pasului 5 i complexitatea total a algoritmului .
31
5. Apropiere i apartenen
Capitolul este consacrat analizei unor probleme geometrice formulate pe puncte n plan: determinarea celei mai apropiate perechi de puncte i apartenena punctului la un domeniu. Soluiile directe ale problemelor de apropiere i apartenen sunt relativ simple, dar nu i optime.
Calculul direct al tuturor distanelor dintre N puncte ne-cesit un numr de 2 operaii pro-porional cu N :
index1 1; index2 2; min distance( s1 , s2 ); For i1 to N do For j1+i to N do If distance( si , s j ) < min then Begin min distance( si , s j ) index1 i; index2 j; End;
Fig. 5.1 Cea mai apropiat pereche de puncte
32
Acelai rezultat poate fi obinut ntr-un timp mai restrns, folosind algoritmul optim cu o complexitate de O( N log N )
33
Algoritmul optim Pentru a determina n timp optim cea mai apro-piat pereche de puncte, poate fi folosit tehnologia recursiv mparte i stp-nete. Ideea major este divizarea la fiecare pas re-cursiv a mulimii Fig. 5.2. Divizarea mulimii n submulimi seiniiale n dou parabile pentru rezolvarea recursiv a problemei cea mai apropiat pereche de puncte submulimi liniar separabile i rezolvarea prob-lemei pe fiecare submul-ime 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 este determinarea soluiei optime la etapa de asamblare: avnd dou submulimi S1 i S 2 , cea mai apropiat pereche de puncte n S1 S2 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 n mulimile asamblate. Numrul de divizri consecutive ale mulimii n submulimi balansate10 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 (irul Y ). Avnd complexitatea
10
O( N log N ) , sortarea nu modific complexitatea final a algoritmului. Fie la un nivel de divizare mulimea S , irul X sortat dup x, irul Y cu elementele S sortate dup y. Aparent, procesul de asamblare a soluiei la un nivel dat
are o complexitate O( N 2 ) : maxim N puncte n S1 i maxim N puncte n S 2 , 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 S 2 , pe care au fost determinate distanele minime 1 i 2 , precum i perechile respective de puncte. Se consider (fig. 5.3) Pentru determina-rea soluiei optime pe
= min( 1, 2 )
S1 S2 este
necesar de a cerceta doar punctele, aflate n fia de lime de la dreapta l care separ submulimile. Celelalte puncte din Fig. 5.3. Determinarea punctelor poteniale pentru submulimi se afl, soluia pe S1 S2 evi-dent, 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
35
Fig. 5.4. Zona de cercetare n S 2 pentru un punct dat
s S1
excluderea din cercetare a tuturor punctelor care se afl n exteriorul dreptunghiului cu latura 2 , asociat punctului s (fig. 5.4). Numrul de puncte din
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 mulimea punctelor care pot m-bunti soluia. Pentru fiecare element din Y se calculeaz distanele doar pn la urm-toarele 8 elemente: ele repre-zint (n cel mai ru caz) simet-ric 6 puncte din din (fig. 5.5). Pseudocod
Preprocesare X S, sort(X) Y S, sort(Y) Procedure apr2p(S, X, Y) If {sortare dup x} {sortare dup y}
S1 plus 6 punc-te
Fig. 5.5. Numrul elementelor consecutive Y care pot modifica distana minim nu depete 9
S 4 then
begin formeaz S1 , S 2 , X 1 , X 2 , Y1, Y2
distance ( Y [i], Y [i+j]) Return end else Return distana minim n S {calculat direct}
carteziene pi ( xi , yi ) . Pentru un punct dat pi S se cere s se determine poligonul V (i ) care va conine toate punctele planului, mai apro-piate de pi dect de oricare alt punct
pj S, pi p j (fig. 5.6).
Problema generalizat pen-tru toate punctele mulimii S este cunoscut sub numele diag-rama Voronoi (fig 5.7). De menionat, c pentru unele puncte ale mulimii S , domeniul determinat de 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 Voro-noi V(i) se bazeaz pe urm-toarea observaie: Dreapta l perpendicular pe mijlocul segmentului pi , p j
37
pi ct i de p j .
dect de
pj
vor forma
semiplanul de-terminat de dreapta l, care conine i punctul Fiecare punct p S este descris prin coordonatele sale car-teziene ( x, y) . Prin urmare, pentru perechea de puncte
pi , p j ,
pentru dreapta l , perpendicular pe segmentul cu extremitile pi , p j , i care trece prin mijlocul acestuia,
dreptei
38
acestuia,
V (i ) =
poate
fi
11
determinat
semiplanul
R( j) :
p R ( j ), d ( p, pi ) < d ( p, p j ).
Atunci
j =1,.., N j i
R ( j ).
Pentru realizarea algoritmului poate fi construit un poligon R de restrngere a planului, astfel nct S R . Cea mai simpl form a poligonului R este un dreptunghi avnd laturile paralele cu axele de coordonate, determinat de punctele diagonale ( xmin , ymin ) , ( xmax , ymax ) :
xmin = min ( xi ) 1 , xmax = max ( xi ) + 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, perpendiculare pe segmentul pi , p j 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 2 - 3 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 .
11
d ( a, b ) =
xa xb + y a y b
39
Utilizarea algoritmului direct pentru determinarea diagra-mei Voronoi nu este eficient: complexitatea algoritmului crete pn la O( N 3 ) . Realizarea eficient a algoritmului de determinare a diagramei Voronoi se bazeaz pe tehnica divizrii consecutive a problemei n mulimi liniar separabile, pn la atingerea Fig. 5.8. Diagramele Voronoi DV(S1) i DV(S2) pn la concatenare. cazurilor elementare, i asamblarea ulterioar a soluiei [11, pag 258 - 269]. Fie S = S1 S 2 i au fost construite diagramele Voronoi
DV ( S1 ), DV (S 2 ) . (fig. 5.8) Pentru asamblarea soluiei vor fi realizate urmtoarele etape: Etapa 1: deter-minarea vectorilor de intrare (ieire) a lan-ului de concatenare: se construiesc muchii-le lips (dou la nu-mr) pentru nfurtoarea convex comu-n a S1 S 2 , se deter-min mijloacele aces-tor muchii i se tra-seaz vectorii perpendiculari pe acestea, i care trec prin punctele de mijloc. Pentru muchia superioar vectorul este orientat spre muchie, pentru cea inferioar de la ea (fig. 5.9). Din Fig. 5.9 Construirea nfurS prin nfurtoarea convex pentru toarei convexe pentruTrasarea adugarea muchiilor.
S1 S2
sunt
eliminate
lan-urile
40
S1
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 construiete de-a lungul vectorului, pn la intersecia cu una din muchiile diagramelor DV (S1 ) sau DV (S 2 ) . n punctul de intersecie direcia vectorului se modific. (fig. 5.10) Modificarea direciei lanului este determinat de modificarea perechii de puncte ntre care se traseaz acesta. Fie, iniial, lanul marcheaz frontiera dintre pi , p j . punctele Atingerea muchii diagramelor unei a
Fig. 5.10. Construirea lanului de concatenare
construite anterior semnific fie nlocuirea pi prin pk (dac muchia atins separ pi , pk ) fie nlocuirea p j prin pk (dac muchia atins separ perechea p j , pk ). Direcia nou a lanului de concatenare este determinat de normala median la segmentul ce unete perechea nou creat. Procesul ia sfrit n momentul atingerii vectorului inferior al lanului de concatenare. Etapa 3: Mo-dificarea muchiilor diagramei. Muchiile infinite (semidrep-te) intersectate de lanul de concate-nare
41
se transform n segmente delimi-tate de originea semidreptei i punctul de intersecie a acesteia cu lanul de concatenare. Muchiile finite (segmentele) i modific unul din punctele extreme, fiind nlocuit cu punctul de intersecie cu lanul de concatenare. Muchiile din DV (S1 ) , situate integral n dreapta de lanul de concatenare, i DV (S 2 ) , muchiile din situate integral n stnga, se exclud din diagrama final. Cazul elementar se obine pentru
2 S 3.
Procesarea acestuia este realizat printr-un numr de operaii mrginit de o constant. Fig. 5.11. Concatenarea diagramelor Divizarea consecutiv a mulimii pentru obinerea cazurilor elementare necesit o sortare prealabil a punctelor din S dup abscisa lor. Complexitatea O( N log N ) . preprocesrii este Numrul de divizri consecutive ale mulimii curente n dou submulimi aproape egale12 este proporional cu log( N ) . Pentru concatenarea soluiilor pariale, n cazul alegerii structurilor de date adecvate este necesar un numr de operaii proporional cu numrul total de muchii din soluiile pariale. Deoarece diagrama Voronoi este o divizare planar a unei mulimi din N puncte, numrul de muchii va fi proporional cu N. Prin urmare, complexitatea to-tal a algoritmului optim este O( N log N ) .
12
poate
fi
determinat n timp constant ( 3.1). Prin urmare, complexitatea algorit-mului este proporional doar cu numrul de laturi ale poligonului. Fie punctual s de coor-donate ( xs , ys ) i poligonul con-vex Fig. 5.12. Punctele interioare sunt plasate de aceeai parte a vectorilor P = ( p1 , p2 , ... , pN ) cu N laturi, determinai de vrfurile consecutive ale descris prin lista vrfurilor, poligonului, poziia celor exterioare poate varia. 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 .
begin if x1*y2+x2*y3+y1*x3-x3*y2-x2*y1-y3*x1 > 0 then verific_punct:=true else verific_punct:=false; end; begin 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;
44
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 segmentele [c, p1 ],[c, p2 ],...,[c, pN ] aparin integral P, poligonul se numete stelat. (fig. 5.13) n cazul, n care punctul interior c este cunoscut Fig. 5.13. P - poligon stelat apriori, determinarea apartenenei unui punct arbitrar s la domeniul interior al poligonului se reduce la verificarea existenei unui triunghi13
Vcpi 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 cunoscut. Apartenena punctului la un poligon simplu Problema apartenenei unui punct s la domeniul determinat de un poligon simplu P poate fi rezolvat prin triangularizarea P i prin verificarea ulterioar a apartenenei s la unul din triun-ghiurile formate n procesul triangularizrii.
13
Un algoritm mai eficient este bazat pe numrarea interseciilor ale dreptei orizon-tale l care trece prin punctul dat s cu laturile poligonului P. (fig. 5.14). Se va cerceta partea dreptei spre stnga de s. Pentru latura curent se determin :
intersecia laturii cu semidreapta l. Dac numrul interseciilor spre stnga de s este impar punctul se afl n interiorul poligonului; pentru un numr par 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. 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.
Fig. 5.14. Numrul de intersecii ale semidreptei l cu laturile poligonului determin apartenena punctului s la interiorul poligonului P.
46
dreapta l conine latura pi 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. dreapta l trece prin 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 intersecii nu se incrementeaz. de
dreapta l conine latura pi 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 ) .
47
5.4. Nuclee
Printre problemele geometrice de calcul se numr i problema nucleului poligonului simplu. Nucleul unui poligon simplu P este, n general, format din mulimea de puncte astfel nct: x Q,y P,[ x, y ] P Cu alte cuvinte, nucleul poligonului este mulimea de puncte ale poligonului, care, fiind unite cu orice alt punct al poli-gonului, formeaz un segment ce aparine interiorului poligonului (fig. 5.15a). Nu ntotdeauna un poligon simplu are nucleu nevid (fig. 5.15.b). Nucleul poligonului (dac el exist) este i el un poligon, dar, spre deosebire de poligonul iniial, este ntotdeauna convex.
Q P,
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:
48
a) construirea nfurtorii convexe pentru P ; b) construirea unui dreptunghi care conine poligonul
n interiorul su.
Metoda a doua este mult mai simpl. Ea se reduce la determinarea, pentru coordonatele vrfurilor poligonului, 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, y min 1) , ( xmin 1, y min 1) , ( xmin 1, y max + 1) . Extinderea valorilor extreme nu este o condiie obligatorie. Dup construcia poligonului Q poate fi realizat nemijlocit determinarea nucleului. 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 se este situat integral n stnga de vectorul 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.16).
uuu u uu r uuu u uu r
49
50
Pseudocod Pas 1. Iniializare La sfritul listei de vrfuri (dup pN ) se adaug vrful virtual pN +1 = p1 . Se construiete poligonul Q (nucleul ini-ial), conform uneia din metodele descrise anterior. i 1;
Pas 2.
determin punctele de intersecie cu poligonul Q , precum i laturile intersectate. Fie d1 , d 2 punctele de intersecie a dreptei l cu Q , iar laturile intersectate:
( q j , q j +1 ) i ( qk , qk +1 ) 14.
a. Se formeaz poligoanele
Q2 = (d 2 , q k +1 , ... , q N , q1 , ... , q j , d1 )
Q1 = (d1 , q j +1 , ... , q k , d 2 ) i
b. Se determin
c. Pas 3.
Q Q*
se
afl
Repetare if i < N then begin i goto pas 2 end else STOP Q este nucleul.
O( N 2 ) . Se Complexitatea algoritmului este de 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.
14
uuu u uu r
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. Exemple
date.in 6 1 3 1 3 5 7 1 8 3 2 3 1 1 3 2 1 -10 10 10 date.out
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. 53
6.2.Robot II
Sistemul de comand al unui robot care poate executa ins-truciuni de deplasare s-a deteriorat. Robotul continu s pri-measc instruciuni, dar le interpreteaz nu ntotdeauna corect. Fiecare instruciune este un triplet de numere
54
Exemplu
date.in 3 2 130 4 1 45 1 7 91 0 3 60 0 6 date.out -0.653 15.697
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. 55
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. Cerin Scriei un program care determin numrul de perei drmai de piatr. Date de intrare Fiierul de intrare 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 va conine un numr ntreg numrul de perei drmai de piatr.
56
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 date.out 4
Rezolvare
program p03; type point=record x,y: real; segment=record e1,e2: point; var g: array[1..1000] of segment; l: segment; n,i,k: integer; end; end;
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.
57
6.4 Carcase
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. Cerin 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 conine trei numere ntregi, separate prin spaiu: N (3 N 1000) - numrul de vrfuri ale carcasei i xc, yc (1000 xc, yc 1000 ) coordonatele centrului de mas. Urmeaz N linii ce conin cte 2 numere ntregi xi, yi (1000 xi, yi 1000), separate prin spaiu, coordonatele vrfurilor poligonului n ordinea parcurgerii lor. Date de ieire Fiierul de ieire va conine un numr ntreg numrul de poziii n care poate fi stabilizat vertical carcasa.
58
Exemplu
drag.in 10 6 16 3 14 13 4 23 14 33 4 33 14 23 24 13 14 3 24 -7 14 -7 4 drag.out 3
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 conine 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 nici unul 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.
59
6.5. Turnuri
Bitlanda este o ar care se extinde permanent. 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. Cerin Scriei 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 turnu-rilor 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
60
6.6
Atac
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. Cerin 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 a punctelor de cdere a meteoriilor sunt numere ntregi din intervalul [-1000000, 1000000]
61
2.
Soluie: Formularea abstract a problemei este urmtoarea: Fie n plan un poligon convex P cu n vrfuri. n acelai plan este dat o mulime din m puncte M. Se cere s se determine cte puncte din M aparin interiorului P. Rezolvarea se divide n cteva etape.
1. Determinarea
xi
i =1
ycm =
y
i =1
62
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) 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;
unde
( x1 , y1 ), ( x2 , y2 )
sunt
coordonatele vrfurilor care determin muchia, 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);
64
6.7. Evadare
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 (3 N 10000) laturi, astfel nct, ieind din tunel, pinguinii nu pot afirma cu certitudine dac se afl n interiorul grdinii zoologice sau n afara ei. Cerin S se scrie un program care, dup coordonatele punctelor extreme ale tunelului i coordonatele vrfurilor poligonului ce stabilete perimetrul grdinii zoologice, va determina dac evada-rea 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 ex-treme ale tunelului. Urmtoarele linii conin descrierea conse-cutiv 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]
65
Exemplu
evadare.in 5 3 7 7 1 2 2 6 6 4 6 7 7 5 10 4 7 2 3 1 evadare.out DA Explicaie
7 5 3 1 1 3 5
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. Cerin S se scrie un program care determin numrul maxim de arcai care pot fi plasai pe poziii de tragere n cmpul de lupt.
66
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 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 9 2 5 3 6 2 7 4 7 6 9 8 6 7 2 5 4 3 4 arcas.out 11
Rezolvare
program p68; type lat=record x,y:real; end; pol=array[0..1001] of lat; var nuc,camp:pol; i,nnuc,ncamp:integer; xint,yint:real; 67
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; 68
end;
69
{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
70
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 else if sarrus(camp[j],camp[j+1],nuc[1])>=0 then
71
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.
72
6.9. Cetate
Arheologii din Bitlanda n timpul spturilor au descoperit nite pietre aezate oarecum straniu. Dup studiere au ajuns la concluzia ca acestea for-meaz fragmente ale unui zid circular, care nconjura o cetate veche. Pentru a proteja de turiti i de curi-oi fragmentele descoperite arheologii au decis s nconjoare fragmentele desco-perite cu un gard din plas metalic. nconjurarea fiecrui fragment este destul de complicat i puin comod, de aceea sa hot-rt s se mprejmuiasc toate fragmentele mpreun. Cerin 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 (1 n 180) a fragmentelor de zid i r (1 r 100) raza zidului. Urmeaz n perechi de numere ntregi, care descriu fragmentele de zid: ai, bi mrimea unghiurilor n grade, care descriu nceputul i sfritul fragmentului. Unghiurile se msoar ncepnd cu direcia nord de la centrul cetii, mpotriva direciei de micare a 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 cetate.out 61.888
73
330 30 90 270
6.10. Druizi
Ruinele din Stonehenge se afl ntr-un loc special, unde se inter-secteaz M linii energetice ale P-mntului. 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 are lungimea laturii L. Liniile energetice sunt linii drepte. Druizii sunt punctiformi i nu se pot afla pe liniile energetice. Cerin 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 2 numere ntregi xi; yi coordonatele druizilor. Toi druizii se afl n interiorul cmpiei, ori care 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 aix + biy + ci = 0, care descrie linia
74
energetic i. Nici un druid nu se afl pe o careva linie. Ori care dou linii nu coincid. Valorile ai, bi, ci nu depesc 10000 dup modul. 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
begin readln(d[i].x,d[i].y); d[i].t:='L'; end; 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}
3. Originea sistemului de coordonate se deplaseaz n punctul de intersecie a dreptelor (liniilor energetice). Apoi se trece la coor-donatele polare pentru punctele ce reprezint druizii i inter-seciile liniilor energetice cu cer-cul. (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; 77
xint:=(-l2b*yint-l2c)/l2a; end; 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}
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}
79
Notaii
u uu uu r p1 p2
-
n
S = { p1 ,..., p N }
S
-
mulimea S, cu elementele p1 ,, pN cardinalul mulimii S incrementarea valorii k cu 1 variabilei k i se atribuie valoarea variabilei m segment cu extremitile a i b. triunghi cu vrfuri n punctele 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 x aparine X (x nu aparine X) submulimea elementelor x din X, care satisfac condiia Q
k k m
[ a, b ]
Vabc
DV ( S ) T (S ) Q(S ) A B A B x X , x X
{ x X : Q}
A B
80
Bibliografie
1. Ammeraal Leen. Programming Principles in Computer Graphics. John Wiley and Sons, 1986. Ammeraal Leen. Computer Graphics for the IBM PC. John Wiley and Sons, 1986. Cerchez Emanuela. Programarea n limbajul C/C++ pentru liceu. Vol III. Polirom, Iai, 2007. Cormen Thomas. Introducere n algoritmi. Agora, Cluj. Foley James, Andries Van Dam. Fundamentals of Interactive Computer Graphics. Addison-Wesley Publishing, 1984. Giumale Cristian. Introducere n analiza algoritmilor. Polirom, Iai, 2004. Sedgewick, Th.; Algorithms in C. Addison Wesley, 2001 Williamson Gill. Combinatorics for Computer Science. Dover publications. New York, 2002. . ++. , , 1997.
2.
3.
4. 5.
6.
7. 8.
9.
12. . . . , , 1985.
13. , .; , . . . : , 1989.
82