Primii pași... Algoritmi ELEMENTARISorin Groza Pentru a putea rezolva cu succes o problemă de informatică este absolut necesar să cunoaștem câțiva algoritmi elementari. Vom prezenta în continuare probleme cu ajutorul cărora vom introduce algoritmi ce vor putea fi folosiți de către "pitici" în rezolvarea problemelor.
ConcursulLa Clubul Copiilor se organizează un concurs la care participă n elevi, fiecare obținând un număr de puncte. Vor fi declarați câștigători toți cei cu punctaj maxim, fiecare primind câte un premiu. Scrieți un program care va determina punctajul maxim și va comunica organizatorilor câte premii să pregătească.
Date de intrare: n=11 16 72 9 7 72 41 12 16 72 16 16
Date de ieșire: Se acorda 3 premii Punctaj maxim: 72 puncte
Pentru rezolvarea aceastei probleme va trebui să găsim cel mai mare punctaj și să determinăm numărul de aparițtii al acestuia în șir. Aici apare unul din algoritmii cel mai des folosiți: determinarea maximului dintr-un șir de numere întregi. Vom considera că cel mai mare element al șirului este cel de pe prima poziție și îl vom păstra într-o variabilă (max). Vom lua, unul câte unul, fiecare element al șirului și le vom compara cu max. În cazul în care un element este mai mare decât max, vom păstra în max valoarea acestuia. După parcurgerea întregului șir, în variabila max vom avea cel mai mare element al șirului. Numărul de premii îl vom calcula cu ajutorul variabilei nr_premii; vom parcurge șirul și, în momentul în care un element este egal cu max, vom incrementa acestă variabilă.
Listing: CONCURS.PAS var i,max,n,nr_premii:Integer; p:array[1..100] of Integer; Begin Write('Introduceti nr. concurentilor: '); Readln(n) Writeln('Punctele concurentilor:'); for i:=1 to n do Read(p[i]); max:=p[1];{ determinarea maximului sirului } for i:=1 to n do if p[i]>max then max:=p[i]; { sfarsit determinare } for i:=1 to n do if p[i]=max then Inc(nr_premii); Writeln('Se acorda ',nr_premii,' premii.'); Writeln('Punctajul maxim ',max,' puncte.') End.
Grupuri În curte se joacă n copii. Ei doresc să formeze grupuri a câte trei copii, astfel încât fiecare grup să aibă proprietatea: înălțimea copilului din mijloc să fie media aritmetică a înălțimilor celorlalți doi copii. Scrieți un program care să afișeze toate grupurile care se pot forma.
Date de intrare: n=6 150 155 154 160 152 156
Date de ieșire: 150 152 154 152 154 156 150 155 160 154 155 156 152 156 160
Pentru a rezolva problema vom genera toate tripletele (prim - mijloc - ultim) și vom verifica dacă respectă condiția cerută. Deoarece, la un moment dat, un grup identificat printr-un triplet nu are valorile ordonate crescător și astfel verificarea proprietății cerute ar fi greoaie, vom ordona crescător înălțimile copiilor. Astfel, fiecare grup format are cele trei valori în ordine crescătoare. Acest algoritm se numește ordonarea crescătoare a unui șir. Parcurgând șirul vom verifica dacă perechile de elemente vecine au valorile ordonate crescător. În caz contrar vom schimba între ele aceste valori. Vom face atâtea treceri până când nu mai au loc astfel de schimbări, moment în care șirul este ordonat crescător.
Listing: GRUPURI.PAS var i,n,prim,mijloc,ultim,aux:Integer; h:array[1..100] of Integer; gata,se_poate:Boolean; Begin Write('Introduceti numarul copiilor '); Readln(n); Writeln('Inaltimile copiilor:'); for i:=1 to n do Read(h[i]); repeat { ordonarea crescatoare a sirului } gata:=true; { metoda "bulelor" } for i:=1 to n-1 do if h[i]>h[i+1]
then begin aux:=h[i]; h[i]:=h[i+1]; h[i+1]:=aux; gata:=false end; until gata; { sfarsit ordonare } for prim:=1 to n-2 do for mijloc:=prim+1 to n-1 do for ultim:=mijloc+1 to n do if h[mijloc]-h[prim]= h[ultim]-h[mijloc]
then begin Write(h[prim],' ',h[mijloc],' '); Writeln(h[ultim]); se_poate:=true end; if not se_poate then Writeln('Nu se pot forma astfel de grupuri') End.
HoțiiUn număr de n hoți ajung la un tezaur care constă din m seifuri, în fiecare seif existând un anumit număr de bani. Hoții vor lua bani dintr-un număr de seifuri consecutive ce respectă proprietatea: suma banilor din aceste seifuri să se împartă exact la cei n hoți (fiecare hoț să "câștige" aceeași sumă) și să fie cea mai mare posibilă de câștigat. Spuneți care dintre seifuri le vor deschide hoții. Dacă problema nu are soluție, se va afișa mesajul Ne lasam de meserie.
Date de intrare: n=4 m=9 2 10 30 3 6 6 6 6 2
Date de ieșire: Deschid seifurile: 2 3
Pentru această problemă vom prezenta doi algoritmi având complexități diferite, adică pentru același set de date timpul de execuție diferă. Rulați aceste două programe cu date identice și observați timpul de execuție! Primul algoritm generează toate subșirurile cuprinse între două poziții i și j, pentru fiecare subșir calculându-se suma elementelor. Dacă această sumă se divide la numărul de hoți și este cea mai mare până în acest moment, se păstrează această secvență, adică poziția de început, poziția de sfârșit și suma elementelor ei. Acest algoritm nu este optim, deoarece face unele calcule de mai multe ori, ceea ce determină creșterea timpului de execuție.
Listing: HOTII_1.PAS var a:array[1..100] of Byte; i,j,x,n,s,nrhoti,max,poz1,poz2:Byte; Begin Write('Introduceti numarul hotilor: '); Readln(nrhoti); Write('Introduceti numarul de seifuri: '); Readln(n); Writeln('Introduceti sumele din seifuri:'); for i:=1 to n do Read(a[i]); for i:=1 to n-1 do { generare subsiruri } begin for j:=i+1 to n do begin for x:=i to j do s:=s+a[x]; if s mod nrhoti=0
then if s>max then begin max:=s; poz1:=i; poz2:=j end; s:=0 end end; { sfarsit generare } if max=0 then begin Writeln('Ne lasam de meserie'); Halt end; Write('Deschid seifele:'); for i:=poz1 to poz2 do Write(i,' ') End.
Al doilea algoritm utilizează un șir care reduce substanțial numărul calculelor și implicit timpul de execuție. Acest șir se numește șirul sumelor parțiale. Astfel, elementul sp[i] va fi egal cu suma tuturor elementelor șirului a de la început până în a i-a poziție: sp[i]=a[1]+a[2]+...+a[i]. Deoarece: sp[i]=a[1]+...a[i-1]+a[i]=sp[i-1]+a[i], se observă relația de calcul a elementelor acestui șir: sp[i]=sp[i-1]+a[i]. Pentru a determina suma valorilor seifurilor între două poziții i și j, nu mai este necesară însumarea a[i]+...+a[j], ci doar o simplă diferență sp[j]-sp[i-1]. Un exemplu concret ar fi următorul: dacă vrem să calculăm suma valorilor seifurilor de la 5 la 9, vom determina diferența dintre sp[9] și sp[4], adică vom scădea din suma primelor 9 seifuri suma primelor 4 seifuri, obținând suma seifurilor de la 5 la 9. Șirul sumelor parțiale poate fi utilizat în rezolvarea multor probleme. Dacă o astfel de secvență are suma mai mare și se divide la numărul hoților, se păstrează poziția de început, poziția de sfârșit și suma secvenței. În final se vor tipări indicii seifurilor ce constituie secvența sau, mesajul cerut în cazul în care nu există o astfel de secvență.
Listing HOTII_2.PAS var a:array[1..100] of Byte; sp:array[0..100] of Word; i,n,nrhoti,max,poz1,poz2,v,p1,p2:Byte; Begin Write('Introduceti numarul hotilor: '); Readln(nrhoti); Write('Introduceti numarul de seifuri: '); Readln(n); Writeln('Introduceti sumele seifurilor:'); for i:=1 to n do Read(a[i]); for i:=1 to n do sp[i]:=sp[i-1]+a[i]; { creare sir sume partiale } { determinare subsir de seifuri } for p1:=0 to n-1 do for p2:=p1+1 to n do begin v:=sp[p2]-sp[p1]; if (v>max) and (v mod nrhoti=0)
then begin max:=sp[p2]-sp[p1]; poz1:=p1; poz2:=p2 end end; { sfarsit determinare } if max=0 then begin Writeln('Ne lasam de meserie '); Halt end; Write('Deschid seifele: '); for i:=poz1+1 to poz2 do Write(i,' ') End.
În încheiere vă propunem să rezolvați câteva probleme. Încercați să scrieți algoritmi diferiți pentru aceeași problemă și să estimați care sunt mai performanți.
ExpozițiaLa expoziția auto de la New York sunt prezentate n mașini, pentru fiecare dintre ele cunoscându-se prețul de vânzare. Scrieți un program care calculează diferența maximă de preț dintre două mașini prezentate.
Date de intrare: n = 5 180 66 90 20 60
Date de ieșire: 160
VizitaÎntr-un sat este agitație, deoarece sosește în vizită o mare personalitate, iar persoana cea mai în vârstă din sat trebuie să o întâmpine cu pâine și sare. Deoarece nu se știe cine este această persoană, este necesar ca toți locuitorii satului să-și declare data nașterii (ziua, luna, anul). Scrieți un program care, plecând de la aceste date, afișează pe ecran data nașterii persoanei celei mai în vârstă din sat.
Date de intrare: n = 5 10 11 1915 22 12 1934 9 1 1955 18 8 1915 25 11 1960
Date de ieșire: persoana cea mai in varsta este nascuta in 18 8 1915
CompetițiaLa un concurs de tras cu frânghia, desfășurat pe plaja din Malibu, participă n persoane, fiecare dintre ele fiind caracterizată de un număr ce reprezintă puterea acesteia. Primii p (pŁn) participanți aparțin echipei stanga, iar ceilalți începând cu poziția p+1, până la ultimul formează echipa dreapta.
Se va considera câștigătoare echipa care are suma puterilor participanților cea mai mare a) citind o poziție p să se spună care echipă va fi învingătoare. b) să se găsească o poziție astfel încât cele două echipe formate să lupte la infinit, adică să aibă aceeași sumă a puterilor. Dacă nu este posibil, să se afișeze mesajul IMPOSIBIL.
Date de intrare: n=7 8 1 3 2 5 3 2 p=4
Date de ieșire: STANGA 3
Domnul Sorin Groza este profesor la Clubul Copiilor din Aiud și poate fi contactat prin intermediul redacției. [cuprins] |