Sunteți pe pagina 1din 46

Probleme rezolvate de programare – Subiecte propuse la ATESTAT

ATESTAT - 2003 - 1 - Se citesc numere naturale până la introducerea a două numere consecutive
egale. Afişaţi toate perechile de numere citite consecutiv, care sunt prime între ele.

Rezolvare:
 Două numere naturale A şi B, diferite de 0, sunt prime “între ele” dacă îl au pe 1 ca singur
divizor comun. Altfel spus, CMMDC al celor două numere este egal cu 1. Nu este obligatoriu ca
A şi B să fie ele însele prime. Exemplu: 15 şi 16 NU sunt numere prime, dar sunt
prime “între ele”, pentru că CMMDC (15, 16) = 1.
 Conform enunţului, dacă “se citesc numere”, nu se ştie de la început “câte” (nu se dă un “n” =
numărul de numere ce se vor citi), deci va trebui să le numărăm cu un contor “i”.
 Numerele pe care le vom introduce vor fi preluate într-un vector X.
 Definim o funcţie CMMDC pentru a calcula CMMDC al două numere consecutive (cele două
numere vor fi două elemente consecutive din vectorul X).
Program ATESTAT_2003_1_NUMERE_PRIME_INTRE_ELE ;
CONST
nmax = 100;
TYPE
vector = array [1..nmax] of integer;
VAR
x : vector;
n, i : integer;
function CMMDC (A, B : integer) : integer;
var
aux, R : integer;
begin
if A < B then
begin
aux := A;
A := B;
B := aux
end;
R := A MOD B;
while R <> 0 do
begin
A := B;
B := R;
R := A MOD B
end;
CMMDC := B
end; { sfarsit functie CMMDC }

Begin { PROGRAM PRINCIPAL }


i := 1; {contor care numara numerele introduse}
write ('Dati x [ ', i,' ] = '); {introducem primul numar}
readln (x [i]);
REPEAT {introducem urmatoarele numere}
i := i + 1;
write ('Dati x [ ', i,' ] = ');
readln (x [i]);
UNTIL ( x [i] = x [i-1] ); {pana ce apar doua numere consecutive egale}

n := i; {n = total numere introduse = i}


for i := 1 to n - 1 do
begin
if CMMDC ( x [i], x [i+1] ) = 1 then
writeln ( x [i],' si ', x [i+1],' sunt prime intre ele');
end;
readln
end.
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ATESTAT - 2003 - 2 - Se citesc numere naturale până la introducerea unui număr prim cu 12.
Afişaţi toate numerele care sunt prime cu suma cifrelor lor.

Rezolvare:
 Două numere sunt prime între ele dacă CMMDC al celor două numere este 1 (vezi problema anterioară).
 Introducem primul număr, notat cu “x”. Verificăm dacă “x” este prim cu 12 şi dacă DA, oprim algoritmul;
dacă nu, verificăm dacă este prim cu suma cifrelor sale.
 Pentru că vom introduce mai multe numere, dar nu ştim de la început câte anume, introducerea
următoarelor numere se va face într-un ciclu WHILE.
 Definim o funcţie CMMDC pentru a calcula CMMDC al două numere.
 Definim o funcţie NUMARACIFRE, pentru a număra cifrele unui număr natural.
 Definim o procedură DETCIFRE, care determină cifrele unui număr şi le depune într-un vector.
 Definim o funcţie SUMACIFRE, care însumează cifrele unui număr.

Program ATESTAT_2003_2_NUMERE_PRIME_CU_SUMA_CIFRELOR_LOR ;
CONST
nmax = 100;
TYPE
vector = array [1..nmax] of integer;
VAR
y : vector;
S, x, n, i : integer;

function CMMDC (A, B : integer) : integer;


var
aux, R : integer;
begin
if A < B then
begin
aux := A;
A := B;
B := aux
end;
R := A MOD B;
while R <> 0 do
begin
A := B;
B := R;
R := A MOD B
end;
CMMDC := B
end; { sfarsit functie CMMDC }

function NUMARACIFRE ( z : integer) : integer;


var
nrcif : integer;
begin
if z = 0 then
nrcif := 1
else
begin
nrcif := 0;
while z > 0 do
begin
z := z DIV 10;
nrcif := nrcif + 1
end;
end;
NUMARACIFRE := nrcif;
end; { sfarsit functie NUMARACIFRE }

4
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
procedure DETCIFRE ( z : integer; VAR y : vector );
{ determina cifrele lui z si le depune in vectorul y }
begin
n := NUMARACIFRE ( z );
i := n;
while i >= 1 do
begin
y [ i ] := z MOD 10;
z := z DIV 10;
i := i - 1
end;
end; { sfarsit proc. DETCIFRE }

function SUMACIFRE ( z : integer) : integer;


var
s : integer;
begin
DETCIFRE ( z, y );
S := 0;
for i := 1 to n do
begin
S := S + y [i]
end;
SUMACIFRE := S;
end; { sfarsit functie SUMACIFRE }

Begin { PROGRAM PRINCIPAL }


write ('Dati x = '); {Introducerea primului număr}
readln ( x );

while CMMDC ( x, 12 ) <> 1 do {testăm dacă x este prim cu 12}


begin

S := SUMACIFRE (x);

if CMMDC (x, S) = 1 then


writeln ('x = ', x,' este prim cu suma cifrelor sale S = ', s)
else
writeln ('x = ', x,' NU este prim cu suma cifrelor sale S = ', s);

write ('Dati x = '); {Introducerea următoarelor numere}


readln ( x );
end;
readln;
end.

ATESTAT - 2003 - 3 - Fie x un număr natural. Stabiliţi care este factorul prim care, în
descompunerea lui x, apare la puterea maximă.

Rezolvare:
 Notăm cu “d” un posibil divizor al lui “x”. Evident, d poate lua valori consecutive începând de la
2 până la x, dar nu orice valoare între 2 şi x este şi divizor al lui x.
 Contorul “nr” numără de câte ori x se împarte exact la un d >= 2.
 După fiecare împărţire exactă a lui x la d, noul x devine x DIV d. Repetăm (într-un ciclu
WHILE) aceste calcule atât timp cât x > 1.

5
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
 Plecăm cu d de la valoarea 2 şi nu de la 1, pentru a evita un ciclu infinit în urma atribuirii
x := x DIV d. Dacă s-ar iniţializa d cu 1, în urma atribuirii x := x DIV d, noua valoare a lui x ar
rămâne întotdeauna = x, deci divizorul d = 1 s-ar număra de o infinitate de ori (găsindu-l pe 1 ca
divizor de o infinitate de ori, nu s-ar mai trece niciodată la d = 2, prin atribuirea d := d + 1).
 Reţinem în variabila ”max” cel mai mare număr de împărţiri ale lui “x” la un divizor “d”.
 Notăm cu ”divizor” divizorul pentru care numărul de împărţiri este “max”.
Program ATESTAT_2003_3 ; {determină divizorul care apare la puterea maximă }

VAR
x, d, nr, MAX, divizor: integer;
Begin { PROGRAM PRINCIPAL }
write ('Dati x = ');
readln (x);

d := 2; {primul divizor posibil}


max := 0; {initializare MAX}
nr := 0; {initializare numar de impartiri ale lui x la d}

while x > 1 do
begin

If x MOD d = 0 then {daca x se imparte la d}


begin
nr := nr + 1;
x := x DIV d;
if max < nr then
begin
max := nr;
writeln ('Divizorul ', d,' apare de ', max, ' ori');
divizor := d;

end
end
else
begin
d := d + 1;
nr := 0
end;
end;
writeln;
writeln ('Divizorul ', divizor,' apare la puterea maxima = ', max);
readln
end.

ATESTAT - 2003 - 4 - Se citesc pe rând n numere naturale. Afişaţi-le pe cele care sunt termeni ai
şirului lui Fibonacci.

Rezolvare:

 Presupunem că numerele “x” NU sunt introduse în ordine.


 Folosim o buclă exterioară în care introducem câte un “x”.
 Folosim o buclă interioară în care generăm un nou termen FIBONACCI, cât timp numărul “x”
introdus rămâne > termenul FIBONACCI generat.
 Termenii şirului FIBONACCI se reţin în vectorul “FIBO”.

6
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Program ATESTAT_2003_4_Fibonacci ;

CONST
nmax = 100;
TYPE
vector = array [1..nmax] of integer;
VAR
FIBO : vector;
x, n, i, j : integer;

Begin { PROGRAM PRINCIPAL }


write ('Dati nr. de numere naturale, n = ');
readln ( n );

for i := 1 to n do {bucla exterioară}


begin
write ('Dati x = ');
readln (x);

FIBO [1] := 1; {iniţializarea primilor termeni ai şirului}


FIBO [2] := 1;

j := 3;

while x > FIBO [j] do {bucla interioară}


begin
FIBO [j] := FIBO [j-1] + FIBO [j-2];
j := j + 1
end; {sfarsit bucla interioară}

if x = FIBO [j] then


writeln ('x = ', x,' este termen FIBO')
else
writeln ('x = ', x,' NU este termen FIBO')

end; {sfarsit bucla exterioară}


readln
end.

ATESTAT - 2003 - 5 - Se citesc pe rând n numere naturale. Afişaţi perechile de numere citite
succesiv, care sunt termeni ai şirului lui Fibonacci.

Rezolvare:
 Definim funcţia VERIFICA, pentru a testa dacă un număr este termen FIBONACCI.
 Numerele pe care le introducem se vor reţine într-un vector “x”.
 Pentru introducerea vectorului, definim procedura CITESTEVECTOR.
Program ATESTAT_2003_5_Fibonacci ;
CONST
nmax = 100;
TYPE
vector = array [1..nmax] of integer;
VAR
x, FIBO : vector;
n, i, j : integer;

7
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
function VERIFICA ( z : integer) : BOOLEAN;
var
OK : BOOLEAN;
begin
OK := FALSE;

FIBO [1] := 1;
FIBO [2] := 1;

if (z = 1) then
OK := TRUE;

j := 3;

while z > FIBO [j] do


begin
FIBO [j] := FIBO [j-1] + FIBO [j-2];
j := j + 1
end;

if z = FIBO [j] then


OK := TRUE;

VERIFICA := OK;

end; { sfarsit functie VERIFICA }

procedure CITESTEVECTOR ( VAR v : vector; n : integer);


begin
for i:= 1 to n do
begin
write ('Dati x [ ', i, ' ] = ');
readln ( v [i] );
end;
end;

Begin { PROGRAM PRINCIPAL }


write ('Dati nr. de numere naturale, n = ');
readln ( n );

CITESTEVECTOR (x, n);

for i := 1 to n-1 do
begin
if ( VERIFICA ( x[i] ) = TRUE ) AND ( VERIFICA ( x[i+1] ) = TRUE ) then
writeln (x [ i ] ,' si ', x [ i + 1 ] ,' sunt termeni FIBO')
else
writeln (x [ i ] ,' si ', x [ i + 1 ] ,' NU sunt termeni FIBO');
end;
readln
end.

ATESTAT - 2003 - 6 - Să se genereze toate numerele de 5 cifre care au doar cifre pare şi sunt
divizibile cu 13.

Rezolvare:
 Notăm cu a, b, c, d, e cifrele numărului x.
 Verificarea se va face pentru toate numerele x cuprinse între 20000 şi 88888.
 Se defineşte o funcţie CIFREPARE, care verifică dacă toate cifrele numărului x sunt pare.

8
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Program ATESTAT_2003_6 ;
VAR
x, y, z, t, u, v, a, b, c, d, e : longint;
function CIFREPARE( z : integer) : BOOLEAN;
begin
e := x MOD 10;
y := x DIV 10;
d := y MOD 10;
z := y DIV 10;
c := z MOD 10;
t := z DIV 10;
b := t MOD 10;
v := t DIV 10;
a := v MOD 10;
if (a MOD 2 = 0) AND (b MOD 2 = 0) AND (c MOD 2 = 0)
AND (d MOD 2 = 0) AND (e MOD 2 = 0) then
CIFREPARE := TRUE
ELSE
CIFREPARE := FALSE;
end; { sfarsit functie CIFREPARE }
Begin { PROGRAM PRINCIPAL }
for x := 20000 to 88888 do
begin
if ( CIFREPARE (x) = TRUE ) AND ( x MOD 13 = 0 ) then
begin
writeln ('x = ', x, ' are toate cifrele pare si se divide la 13');
writeln ('Apasati ENTER');
readln
end;
end;
readln
end.

ATESTAT - 2003 - 7 - Să se genereze toate numerele de 6 cifre, care au cifrele ordonate


descrescător, prima şi ultima cifră fiind impare.

Rezolvare:
 Notăm cu a, b, c, d, e, f cifrele numărului x.
 Definim funcţia VERIFICA (x), care determină cifrele lui x si apoi face verificările impuse de
problemă.
 Numerele testate sunt cuprinse între 987653 şi 654321.
Program ATESTAT_2003_7 ;
VAR
x, y, z, t, u, v, w, a, b, c, d, e, f : longint;
function VERIFICA ( z : longint) : BOOLEAN;
begin
f := x MOD 10; {determinarea cifrelor lui x}
y := x DIV 10;
e := y MOD 10;
z := y DIV 10;
d := z MOD 10;
t := z DIV 10;
c := t MOD 10;
v := t DIV 10;
b := v MOD 10;
w := v DIV 10;
a := w MOD 10;

9
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
if (a > b) AND (b >c) AND (c >d)
AND (d >e) AND (e >f) then
begin
if (a MOD 2 <> 0 ) AND (f MOD 2 <> 0) then
VERIFICA := TRUE
else
VERIFICA := FALSE
end
else
VERIFICA := FALSE;

end; { sfarsit functie VERIFICA }

Begin { PROGRAM PRINCIPAL }

for x := 987653 downto 654321 do


begin
if VERIFICA (x) = TRUE then
begin
writeln ('x = ', x );
writeln ('Apasati ENTER');
readln
end;
end;
readln
end.

ATESTAT - 2003 - 8 - Să se determine toate cuvintele de 5 litere ce conţin măcar două vocale şi au
a 2-a literă “m”.

Rezolvare:
 Generăm cuvintele folosind un şir de caractere “cuvant” de lungime = 5.
 Pe poziţia 2 din “cuvant” va fi întotdeauna litera “m”, deci cuvant [2] := 'm'.
 Pe celelalte 4 poziţii (1, 3, 4, 5) din “cuvant” vom plasa consoane şi vocale. Pentru aceasta,
folosim 4 bucle “FOR” în care contorii de tip CHAR vor fi chiar elementele şirului “cuvant” de
pe poziţiile 1, 3, 4, 5 (cuvant [1], cuvant [3], cuvant [4], cuvant [5]), care vor lua valori de tip
CHAR de la ‘a’ la ’z’.
 Pentru fiecare poziţie din şirul “cuvant” testăm dacă pe poziţia respectivă se află o vocală şi dacă
DA, numărăm acea vocală, folosind contorul nrvocale.
 După generarea unei combinaţii de vocale şi consoane care compun un cuvânt (la sfârşitul buclei
FOR de la interior), testăm dacă nrvocale >= 2 şi dacă DA, numărăm cuvântul care satisface
condiţiile problemei (majorăm contorul “i”) şi afişăm cuvântul.
 La începutul buclei “FOR” situate cel mai interior, trebuie să iniţializăm, de fiecare dată,
contorul care numără vocalele, scriind nrvocale := 0;
Program ATESTAT_2003_8 ;

uses crt;

var
cuvant : string;
i, nrvocale : integer;

Begin { PROGRAM PRINCIPAL }


i := 0; {i = contor care numără cuvintele pe care le vom genera}
cuvant [2] := 'm';

10
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
for cuvant [1] := 'a' to 'z' do
begin
for cuvant [3] := 'a' to 'z' do
begin
for cuvant [4] := 'a' to 'z' do
begin
for cuvant [5] := 'a' to 'z' do
begin
nrvocale := 0; {contor ce numără vocalele din “cuvant”}
if cuvant [1] IN ['a','e','o','i','u'] then
nrvocale := nrvocale + 1;
if cuvant [3] IN ['a','e','o','i','u'] then
nrvocale := nrvocale + 1;
if cuvant [4] IN ['a','e','o','i','u'] then
nrvocale := nrvocale + 1;
if cuvant [5] IN ['a','e','o','i','u'] then
nrvocale := nrvocale + 1;
if nrvocale >= 2 then
begin
i := i + 1;
writeln ('i = ', i);
writeln ('cuvantul = ', cuvant [1], cuvant[2],
cuvant[3], cuvant[4], cuvant[5]);
end;
readln
end
end;
end;
end;
readln
end.

ATESTAT - 2003 - 9 - Să se afişeze toate matricile pătratice n x n care conţin pe fiecare linie şi
coloană un singur 1, în rest 0.

Rezolvare:
Această problemă este asemănătoare cu “problema celor n regine”, pe care o vom adapta la
cerinţele de mai sus. Asociem unei regine o cifră de 1. Problema reginelor cere să se plaseze n
regine pe o tablă de şah de dimensiune n x n, astfel încît oricare două regine să nu se atace. Pentru
ca două regine să nu se atace, ele trebuie să nu fie situate pe aceeaşi linie, pe aceeaşi coloană sau pe
aceeaşi diagonală. La noi, rolul reginelor va fi jucat de elementele egale cu 1 din matricea pătratică n x
n. În cazul problemei noastre, vom renunţa la cerinţa ca elementele matricii egale cu 1 să nu fie plasate
pe aceeaşi diagonală. Pe fiecare linie trebuie să fie plasată cîte o regină. Deci, pentru ca poziţia reginelor
să fie complet determinată, este suficient să reţinem, pentru fiecare regină, coloana în care este plasată,
într-un vector soluţie f, de dimensiune n, unde f [i] reprezintă coloana în care este plasată regina de pe
linia i. Generarea matricilor în condiţiile problemei se face apelând la un algoritm “backtracking”.

Observaţii:
Notăm cu x, respectiv i o linie oarecare şi cu f [x], respectiv f [i], coloana pe care se găseşte
regina de pe linia x, respectiv linia i.

Condiţiile interne:
a). f [x] = 1, 2, ..., n, pentru oricare x = 1, 2, ..., n
b). Două regine nu pot fi plasate pe aceeaşi coloană se va exprima analitic astfel:
f [x] ≠ f [y] pentru orice x ≠ y, cu x, y = 1, 2,...,n.
Definim o procedură AFIŞARE astfel:

11
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
În momentul apelării procedurii, este evident că s-a găsit o soluţie pe care o numărăm scriind:
Nrsol := Nrsol + 1
şi apoi afişăm Nrsol.
Vom parcurge toate coloanele de la 1 la n. Pentru aceasta avem nevoie de un contor poziţional
col care va lua valori de la 1 la n.
În procedură, col este o coloană curentă, iar f [lin] este tot o coloană, şi anume coloana pe
care se găseşte regina de pe linia lin.
Procedura va tipări " * " dacă pe coloana curentă col există o regină, adică atunci când col
= f [lin], şi va tipări "o" dacă această condiţie nu este satisfăcută.

Program ATESTAT_2003_9 ;
uses crt;
const
nrmaxregine = 8; {8 sau altă valoare}
type
vectorsolutie = array [0..nrmaxregine] of 0..nrmaxregine;
var
f : vectorsolutie;
n, x, i : 0 .. nrmaxregine;
ok : boolean;
nrsol : word;

procedure AFISARE;
var
i, j : 0 ..nrmaxregine;
begin
nrsol := nrsol + 1;
writeln;
writeln ('Solutia nr. ',nrsol);
for i := 1 to n do
begin
for j := 1 to n do
begin
if j = f [i] then
write (' 1 ')
else
write (' o ')
end;
writeln;
end;
writeln;
readln
end; { sfarsit procedura }

Begin { PROGRAM PRINCIPAL }


clrscr;
write ('Introduceti numarul de patratele n = ');
readln (n);

nrsol:=0;
x := 1; { virful stivei }
f [x] := 0;

while x > 0 do { cit timp stiva nu este vida }


begin
while f [x] < n do { cit timp exista valori disponibile }
begin
f [x] := f [x] + 1;
ok := true;

12
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
for i := 1 to x - 1 do
begin
if ( f[i] = f [x] ) then
begin
ok := false;
end
end;
if ok = true then { valoarea este valida }
begin
if x = n then { stiva este plina }
AFISARE
else
begin
x := x + 1; {PAS INAINTE}
f [x] := 0
end;
end;
end; { sfarsit WHILE interior }
x := x – 1 {PAS INAPOI}
end; { sfarsit WHILE exterior }
readln
end.

ATESTAT - 2003 - 10 - Să se genereze toate permutările mulţimii {1, 2,... n} cu condiţia ca orice
două numere alăturate ale unei permutării să fie prime între ele.

Rezolvare:

 Definim o funcţie CMMDC pentru a calcula CMMDC al două numere.


 Funcţia CMMDC va fi apelată în procedura PERMUTĂ, pentru a se testa dacă două numere
alăturate ale unei permutări sunt prime între ele. Cu excepţia acestei verificări impuse de enunţul
problemei de faţă, procedura PERMUTĂ are acelaşi conţinut ca şi cel de la generarea
permutărilor de ordinul n.
Program ATESTAT_2003_10_PERMUTARI ;
uses crt;
const
nmax = 100;
type
vector = array [1..nmax] of integer;
var
f : vector;
sol, n, i : integer;
OK : boolean;
function CMMDC (A, B : integer) : integer;
var
aux, R : integer;
begin
if A < B then
begin
aux := A;
A := B;
B := aux
end;

13
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
R := A MOD B;
while R <> 0 do
begin
A := B;
B := R;
R := A MOD B
end;
CMMDC := B
end; { sfarsit functie CMMDC }

procedure VERIFICA ( k : integer; f : vector ; VAR CONTIN : boolean );


LABEL
10;
begin
CONTIN := TRUE;
for i := 1 to k - 1 do
begin
if f [i] = f [k] then
begin
CONTIN := FALSE;
GOTO 10
end;
end;
10:
end;

procedure SCRIE ;
begin
sol := sol + 1;

write ('Solutia nr. ',sol,' ');

for i := 1 to n do
begin
write ( f [i] : 3 )
end;
writeln

end;

procedure PERMUTA ( m : integer );


LABEL
20;
var
k : integer;
CONTIN : boolean;
Begin {început procedură PERMUTA}
k := 1;
f [k] := 0;
while k > 0 do
begin
CONTIN := FALSE;
while f [k] < m do
begin
f [k] := f [k] + 1;
VERIFICA (k, f, CONTIN);
if CONTIN = TRUE then
GOTO 20
end;
20: if ( CONTIN = TRUE ) AND (k = n) then
begin
OK := TRUE;

14
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
for i := 1 to n - 1 do
begin
if CMMDC ( f[i], f[i-1] ) <> 1 then
OK := FALSE
end;
if OK = TRUE then
SCRIE;
end;
if ( CONTIN = TRUE ) and (k < n) then
begin
k := k + 1;
f [k] := 0
end;
if CONTIN = FALSE then
k := k - 1
end; {sfârşit WHILE exterior}
end; {sfârşit procedură PERMUTA}

Begin { PROGRAM PRINCIPAL }


clrscr;

sol := 0;

write('Dati n = ');
readln (n);

writeln;

PERMUTA (n);

if sol = 0 then
writeln ('Nu exista solutie');

readln
end.

ATESTAT - 2003 - 11 - Să se genereze toate variantele de punctaje ce aparţin {1, 2,... 10}
obţinute la n examene, astfel încât punctajul obţinut să fie minim.

Rezolvare:

Generarea combinaţiilor de note se face după algoritmul BACKTRACKING.


 Folosim un vector max în care memorăm nota maximă obţinută la fiecare din cele n examene.
Evident, vectorul max va avea n elemente.
 În algoritmul de generare a produsului cartezian din lucrarea amintită, am notat cu f [x] o valoare
numerică dintr-o poziţie x. Adaptăm aceste notaţii la problema noastră: în loc de x notăm cu poz
poziţia în care se găseşte o notă în combinaţia de note care va fi generată şi cu nota [poz], nota
de pe poziţia poz. Poziţia poz va lua valori de la 1 la n (n = total examene). Evident, nota va fi
un vector cu max [i] elemente, unde i este numărul de ordine al unui examen.

15
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Program ATESTAT_2003_11_Produs_cartezian_EXAMENE;
uses CRT;
type
vector = array [1..20] of integer; {20 = nr. de examene}
var
i, poz, n : integer;
max, nota : vector;
S, min : integer;
procedure SCRIE;
begin
write ('{ ');
for i := 1 to n - 1 do
begin
write ( nota[i],' , ');
end;
write ( nota[n],' ');
write ('} ');
writeln;
end;

Begin { PROGRAM PRINCIPAL }


CLRSCR;
write ('Introduceti numarul de EXAMENE, n = ');
readln (n);
writeln;
writeln (‘Pentru fiecare examen, precizati care este nota MAXIMA’);
writeln ('Scrieti 10 pt. note de la 1 la 10 : ');
writeln;
for i:= 1 to n do
begin
write ('Pentru examenul ', i, ' Care este nota MAXIMA ? ');
readln ( max [i] );
end;
writeln;
Writeln ('Punctajul minim = suma notelor la fiecare examen');
write ('Precizati punctajul MINIM pe care vreti sa-l obtineti, Min = ');
readln (min);
poz := 1; {Început algoritm BACKTRACKING}
nota [poz] := 0;
while poz > 0 do
begin
if nota [poz] < max [poz] then
begin
nota [poz] := nota [poz] + 1;
if poz = n then
begin
S := 0;
for i := 1 to n do
S := S + nota [i] ;
if S = min then
SCRIE;
end
else
begin
poz := poz + 1; {PAS ÎNAINTE}
nota [poz] := 0
end
end
else
poz := poz – 1 {PAS ÎNAPOI}
end;
readln
end.

16
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ATESTAT - 2003 - 12 - Afişaţi numere prime mai mici decât un număr “n” citit de la tastatură,
care rămân prime şi după ce au fost inversate.

Rezolvare:
 Definim o funcţie PRIM, cu rezultat de tip BOOLEAN, care testează dacă un număr este prim.
 Definim o funcţie INVERS care inversează elementele unui şir.
 În programul principal, înainte de a inversa un număr x, îl transformăm mai întâi într-un şir cu
funcţia STR.
 După inversare, transformăm şirul obţinut într-un număr cu funcţia VAL.
 Testăm dacă numărul obţinut prin inversare este şi el prim.
Program ATESTAT_2003_12 ;
uses crt;
var
inversul, sir : string;
a, b, i, x, n, invx : integer;

function PRIM (x : integer ) : boolean;


var
nrdiv, diviz : integer;
begin
nrdiv := 0;
diviz := 1;
while diviz <= x do
begin
if x MOD diviz = 0 then
nrdiv := nrdiv + 1;
diviz := diviz + 1
end;
if nrdiv = 2 then
PRIM := TRUE
else
PRIM := FALSE;
end;

function INVERS (s : string) : string;


var
inv : string;
begin
inv := '';
for i := LENGTH (s) DOWNTO 1 do
begin
inv := inv + s [i]
end;
INVERS := inv ;
end;

Begin { PROGRAM PRINCIPAL }


clrscr;

write('Dati n = ');
readln (n);
writeln;

for x := 1 to n do
begin
STR (x, sir);
inversul := INVERS (sir);
VAL (inversul, a, b);
invx := a;

17
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
if PRIM (x) = TRUE then
begin
if PRIM (invx) = TRUE then
begin
writeln ('x = ', x,' = prim');
writeln ('invx = ', invx,' = prim');
end;
end;
end;
readln
end.

ATESTAT - 2003 - 13 - Se citeşte un vector cu n componente numere întregi. Să se determine


CMMDC al valorilor din vector.

Rezolvare:
 Definim funcţia CMMDC cu care calculăm CMMDC al două numere.
 Calculăm CMMDC al primelor două numere din vector (x1 si x2) şi îl notăm cu C[1].
 Începând de la i = 2 până la n, facem atribuirile:
x [i] := C [i-1];
C [i] := CMMDC ( x [i], x [i+1] )
Altfel spus, calculăm CMMDC dintre CMMDC-ul anterior şi următorul element al vectorului.
Program ATESTAT_2003_13 ;
uses crt;
const
nmax = 100;
type
vector = array [1..nmax] of integer;
var
x, C : vector;
sol, n, i : integer;

function CMMDC (A, B : integer) : integer;


var
aux, R : integer;
begin
if A < B then
begin
aux := A;
A := B;
B := aux
end;
R := A MOD B;

while R <> 0 do
begin
A := B;
B := R;
R := A MOD B
end;
CMMDC := B
end; { sfarsit functie CMMDC }

Begin { PROGRAM PRINCIPAL }


clrscr;
write('Dati n = ');
readln (n);
writeln;

18
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
writeln ('Dati vectorul');
writeln;
for i := 1 to n do
begin
write ('Dati x [ ', i, ' ] = ');
readln ( x [i] );
end;

C [1] := CMMDC ( x[1], x [2] );

for i := 2 to n-1 do
begin
x [i] := C [i-1];
C [i] := CMMDC ( x [i], x [i+1] )
end;

writeln ('CMMDC = ', C [n-1] );

readln
end.

ATESTAT - 2003 - 14 - Se citesc 2 numere naturale A < B. Să se tipărească toate numerele


PALINDROAME dintre A şi B. Un număr este PALINDROM dacă, citit direct şi invers, rezultatul
este acelaşi (dacă este egal cu inversul său). Exemplu: 323 este PALINDROM.

Rezolvare:
 Definim o funcţie NRCIFRE pentru a număra cifrele unui număr natural.
 Definim o funcţie PALINDROM în care:
- determinăm numărul de cifre pentru un număr natural;
- extragem din numărul natural cifrele şi le depunem într-un vector “y”;
- verificăm dacă vectorul “y” este simetric (PALINDROM).
 În programul principal, apelăm funcţia PALINDROM pentru toate numerele naturale dintre A
şi B şi le afişăm doar pe acelea care sunt palindroame.

Program ATESTAT_2003_14 ;
uses crt;
VAR
A, B, x, n, nrcif, i : integer;
OK : boolean;
y : array [1..100] of integer;

function NRCIFRE (x : integer) : integer;


begin
if x = 0 then
nrcif := 1
else
begin
nrcif := 0;
while x <> 0 do
begin
nrcif := nrcif + 1;
x := x DIV 10
end;
end;
NRCIFRE := nrcif
end;

19
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
function PALINDROM ( x : integer ) : boolean;
begin
n := NRCIFRE (x);
for i := n DOWNTO 1 do
begin
y [i] := x MOD 10;
x := x DIV 10;
end;

OK := TRUE;

for i := 1 to n DIV 2 do
begin
if y [i] <> y [n-i+1] then
OK := FALSE
end;
PALINDROM := OK
end;

Begin { PROGRAM PRINCIPAL }


clrscr;
write ('Dati A = '); readln (A);
writeln;
write ('Dati B = '); readln (B);
writeln;
clrscr;
for x := A to B do
begin
if PALINDROM (x) = TRUE then
writeln ('x = ', x, ' este PALINDROM');
{ else
writeln ('x = ', x, ' NU este palindrom'); }
{readln;}
end;

readln
end.

ATESTAT - 2003 - 15 - Se citeşte un vector cu n componente întregi. Care este cea mai mare sumă
care se poate forma cu ele?
Exemplu: n = 4, iar numerele citite sunt –1, 3, 2, -7. Se va tipări 5.

Rezolvare:
 Numerele întregi introduse vor fi reţinute într-un vector x.
 Numerele întregi introduse pot fi pozitive, negative sau nule. Evident, suma cea mai mare ce se
poate obţine din întregul şir de numere va rezulta prin însumarea doar a numerelor pozitive.
 Notăm cu Spoz suma numerelor strict pozitive. Într-o buclă FOR, vom adăuga la această sumă
câte un termen, doar dacă acest termen este strict > 0.
Program ATESTAT_2003_15 ;

uses crt;

VAR
Spoz, n, i : integer;
x : array [1..100] of integer;

20
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Begin { PROGRAM PRINCIPAL }
clrscr;

write ('Dati n = ');


readln (n);
writeln;

writeln ('Dati vectorul');


for i := 1 to n do
begin
write ('Dati x [ ', i, ' ] = ');
readln ( x [i] );
end;

writeln;

Spoz := 0;

for i := 1 to n do
begin
if x [i] > 0 then
Spoz := Spoz + x [i];
end;
writeln ('Spoz = ', Spoz);

readln
end.

ATESTAT - 2003 - 16 – Interschimbaţi coloanele unei matrici cu m linii şi n coloane astfel încât,
în linia k, elementele să fie ordonate crescător.

Rezolvare:
 Ordonăm linia “k”. În cursul procesului de ordonare, o parte din elementele liniei “k” se
interschimbă între ele.
 În paralel cu ordonarea, interschimbăm şi coloanele corespunzătoare elementelor de pe linia “k”
supuse interschimbărilor.

Program ATESTAT_2003_16 ;
uses crt;
VAR
OK, m, n, i, j, k : integer;
A : array [1..100, 1..100] of integer;
aux : integer;

Begin { PROGRAM PRINCIPAL }


clrscr;

write('Dati m = ');
readln (m);
writeln;

write ('Dati n = ');


readln (n);
writeln;

write ('Dati linia k = ');


readln (k);
writeln;

21
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
writeln ('Dati matricea');
for i := 1 to m do
begin
for j := 1 to n do
begin
write ('Dati A [ ', i, ',', j, ' ] = ');
readln ( A [i,j] );
end;
end;

REPEAT {Ordonăm linia k, prin metoda BUBBLE-SORT}


OK := 0;
j := 1;
REPEAT
if A [k, j] > A [k, j+1] then
begin
for i := 1 to m do
begin
aux := A [i, j];
A [i, j] := A [i, j+1];
A [i, j+1] := aux;
OK := 1;

end;
end;
j := j + 1;
UNTIL (j > n - 1) ;
UNTIL (OK = 0);
writeln;
writeln ('Matricea ordonata este');
for i := 1 to m do
begin
for j := 1 to n do
begin
write ('A [ ', i, ',', j, ' ] = ', A [i,j],' ' );
end;
writeln;
end;
readln
end.

ATESTAT - 2003 - 17 - Se citeşte un text şi o succesiune de caractere. De câte ori întâlnim această
succesiune în cadrul textului ?

Rezolvare:
 Apelăm funcţia POS (subşir, şir) şi determinăm poziţia unde apare subşir în şir.
 Dacă poziţia determinată este <> 0, atunci majorăm contorul nrapariţii, care numără apariţiile
subşirului în şir.
 De asemenea, dacă poziţia determinată este <> 0, ştergem din şirul dat caracterele, de la poziţia
1, pe o lungime = poziţia + LENGTH (subşir) – 1, unde poziţia este valoarea determinată cu
funcţia POS.

22
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Program ATESTAT_2003_17 ;
uses crt;
var
sir, subsir : string;
pozitia, nraparitii : integer;
OK : boolean;
Begin { PROGRAM PRINCIPAL }
clrscr;
write('Dati sirul = ');
readln (sir);
writeln;
writeln ('Dati subsirul = ');
readln (subsir);
writeln;
nraparitii := 0;
OK := TRUE; { presupun ca subsirul exista }
while (sir <> '' ) AND ( OK = TRUE ) do
begin
pozitia := POS (subsir, sir);
if pozitia <> 0 then
begin
nraparitii := nraparitii + 1 ;
DELETE (sir, 1, pozitia + LENGTH (subsir) - 1 )
end
else
OK := FALSE
end;
writeln ('nraparitii = ', nraparitii);
readln
end.

ATESTAT - 2003 - 18 - Problema celor 8 regine. Să se afişeze toate posibilităţile de a se aşeza, pe


o tablă de şah, 8 regine fără să se atace între ele.

Rezolvare:
Problema reginelor cere să se plaseze n regine pe o tablă de şah de dimensiune n x n astfel încît
oricare două regine să nu se atace. Pentru ca două regine să nu se atace, ele trebuie să nu fie situate pe
aceeaşi linie, pe aceeaşi coloană sau pe aceeaşi diagonală. Pe fiecare linie trebuie să fie plasată cîte o
regină. Deci, pentru ca poziţia reginelor să fie complet determinată, este suficient să reţinem, pentru
fiecare regină, coloana în care este plasată, într-un vector soluţie f, de dimensiune n, unde f [i]
reprezintă coloana în care este plasată regina de pe linia i. Generarea matricilor care afişează poziţiile
reginelor, în condiţiile problemei, se va face apelând la un algoritm “backtracking”.
Observaţii:
Notăm cu x, respectiv i o linie oarecare şi cu f [x], respectiv f [i] coloana pe care se găseşte
regina de pe linia x, respectiv linia i.
Condiţiile interne:
a). f [x] = 1, 2, ..., n, pentru oricare x = 1, 2, ..., n
b). Condiţia “două regine nu pot fi plasate pe aceeaşi coloană” se va exprima analitic astfel:
f [x] ≠ f [y] pentru orice x ≠ y, cu x, y = 1, 2,...,n.
c). Două regine nu pot fi plasate pe aceeaşi diagonală. Dacă regina de pe linia i, coloana f [i] este pe
aceeaşi diagonală cu regina de pe linia x, coloana f [x], atunci triunghiul dreptunghic care se formează
are unghiurile de 45 grade, este deci isoscel (catetele sale vor fi egale), ceea ce se poate scrie astfel:
|i-x|=|f[i]-f[x]|
Cum acest lucru nu este permis de problemă, condiţia “două regine nu pot fi plasate pe aceeaşi
diagonală” se va exprima astfel:
| f [i] - f [x] | <> | i - x | pentru orice i, x = 1, 2, ..., n

23
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Definim o procedură AFIŞARE astfel încât:
 În momentul apelării procedurii, evident s-a găsit o soluţie pe care o numărăm scriind:
Nrsol := Nrsol + 1
şi apoi afişăm Nrsol.
 Vom parcurge toate coloanele de la 1 la n. Pentru aceasta avem nevoie de un contor poziţional col
care va lua valori de la 1 la n.
 În procedură, col este o coloană curentă, iar f [lin] este tot o coloană, şi anume coloana pe care se
găseşte regina de pe linia lin.
 Procedura va tipări " * " dacă pe coloana curentă col există o regină, adică atunci când
col = f [lin], şi va tipări "o" dacă această condiţie nu este satisfăcută.
Program ATESTAT_2003_18_REGINE ;
uses crt;
const
nrmaxregine = 8;
type
vectorsolutie = array [0..nrmaxregine] of 0..nrmaxregine;
var
f : vectorsolutie;
n, x, i : 0 .. nrmaxregine;
ok : boolean;
nrsol : word;
procedure AFISARE;
var
i, j : 0 ..nrmaxregine;
begin

nrsol := nrsol + 1;
writeln;
writeln ('Solutia nr. ',nrsol);
for i := 1 to n do
begin
for j := 1 to n do
begin
if j = f [i] then
write (' * ')
else
write (' o ')
end;
writeln;
end;
writeln;
readln
end; { sfarsit procedura }

Begin { PROGRAM PRINCIPAL }


clrscr;
write ('Introduceti numarul de patratele n = ');
readln (n);
nrsol:=0;
x := 1; { virful stivei }
f [x] := 0;

while x > 0 do { cât timp stiva nu este vidă – început algoritm }


begin { backtracking }
while f [x] < n do { cât timp există valori disponibile }
begin
f [x] := f [x] + 1;

24
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ok := true;
for i := 1 to x - 1 do
begin
if (f[i] = f [x]) OR (ABS (i-x) = ABS (f[i] - f[x])) then
begin
ok := false;
end
end;
if ok = true then { valoarea este validă }
begin
if x = n then { stiva este plină }
AFISARE
else
begin
x := x + 1; {PAS ÎNAINTE}
f [x] := 0
end;
end;
end; { sfarsit WHILE interior }
x := x – 1 {PAS ÎNAPOI}
end; { sfarsit WHILE exterior }
readln
end.

ATESTAT - 2003 - 19 - Se dau două numere naturale n şi k. Să se genereze toate combinările de n


elemente luate câte k.

Rezolvare: Aplicăm algoritmul BACKTRACKING pentru generarea combinărilor.


Program ATESTAT_2003_19_COMBINARI_BACKTRACKING_1 ;
uses CRT;
CONST
Kmax = 20; { nr. max a lui k }
Nmax = 50; { nr. max a lui n }
TYPE
functie = array [ 1 .. Kmax ] of 0 .. Nmax;
VAR
k, poz, i : 1 .. Kmax; { se considera k <= n }
n : 0 .. Nmax;
f : functie;
IMAG : set of 1 .. Nmax; { IMAG = multimea imaginilor elementelor din A }
{ adica f [poz] }
Begin { PROGRAM PRINCIPAL }
clrscr;
REPEAT
write ('k = ');
readln (k);
UNTIL ( k >= 1 ) AND ( k <= Kmax);

REPEAT
write ('Introduceti un n >= ', k,' n = ');
readln (n);
if n < k then
writeln ('Pentru acest n = ', n,' Nu exista solutii')
UNTIL ( n >= k) AND ( n >= 1 ) AND ( n<= Nmax );
writeln;

25
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
poz := 1; {poz = vârful stivei }
f [poz] := 0 ;

while poz > 0 do { cât timp stiva nu este vidă }


begin
while f [poz] < n - k + poz do { a doua condiţie internă }
begin
f [poz] := f [poz] + 1;
if poz = k then { dacă stiva este plină }
begin
for i := 1 to k do
begin
write ( 'f [',i,'] = ',f[i] , ' ');
end;
writeln;
writeln
end
else
begin
poz := poz + 1 ; { INSERARE in STIVA }
f [poz] := f [poz - 1]
end;
end; { sfarsit WHILE interior }
poz := poz - 1; { EXTRAGERE din STIVA = PAS INAPOI}
end; { sfarsit WHILE exterior }
readln
end.

ATESTAT - 2003 - 20 - Să se genereze toate şirurile de lungime “n” formate numai din literele “A”
şi “M”, şiruri care să nu aibă două litere “A” alăturate. Numărul “n” (0 < n < 13) se citeşte de la
tastatură. Fiecare şir va fi scris pe câte un rând al ecranului fără spaţiu între litere.

Rezolvare:
Problema constă în generarea produsului cartezian al mulţimilor de caractere. Generarea
combinaţiilor de litere se face după algoritmul BACKTRACKING.
 Algoritmul de generare a produsului cartezian va genera valori numerice cuprinse între 1 şi
elementul maxim al unei mulţimi implicate în acest produs. Cum pe noi ne interesează
combinaţiile de litere “a” şi “m”, vom asocia unui număr din câte o mulţime o literă, astfel:
dacă f [i] = 1, atunci sir [i] = ‘a’
dacă f [i] = 2, atunci sir [i] = ‘m’.
Nu ne interesează decât aceste valori ale lui f [i].
 Procedura SCRIE se va apela în mod opţional, pentru a observa modul de generare a produsului
cartezian în varianta sa numerică.
 Procedura SCRIETEXT va afişa doar combinaţiile de litere “a” şi “m”.
 Funcţia booleană VECINI testează dacă avem litera “a” pe două poziţii vecine.
 Funcţia booleană EXISTĂ verifică dacă în şir există şi cifra 1. În acest fel se vor elimina
combinaţiile care nu-l conţin pe 1 (adică acele combinaţii de litere care nu conţin litera “a” şi
care, deci, nu ne interesează).
 Vectorul “nrelem” reţine numărul de elemente al fiecărei mulţimi din produsul cartezian.
 “Poz” = poziţia unui element într-o mulţime a produsului cartezian.

26
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Program ATESTAT_2003_20_Produs_cartezian_AMA ;
uses CRT;
type
vector = array [1..20] of integer;
var
i, poz, n : integer;
nrelem, f : vector;
sir : string;
procedure SCRIE; {procedura opţională}
begin
write ('{ ');
for i := 1 to n - 1 do
begin
write (f[i],' , ');
end;
write ( f[n],' '); write ('} ');
writeln;
end;
procedure SCRIETEXT;
begin
for i := 1 to n do
begin
if f [i] = 1 then
sir [i] := 'a';
if f [i] = 2 then
sir [i] := 'm';
write ( sir [i], ' ' );
end;
writeln;
end;
function VECINI: boolean;
var
OK : boolean;
begin
OK := FALSE;
for i:= 1 to n - 1 do
begin
if (f [i] = 1 ) AND (f [i + 1] = 1) then
OK := TRUE
end;
VECINI := OK
end;
function EXISTA : boolean; { verifica daca in sir exista si cifra 1 }
var
OK : boolean;
begin
OK := FALSE;
for i:= 1 to n do
begin
if f [i] = 1 then
OK := TRUE
end;
EXISTA := OK;
end;
Begin { PROGRAM PRINCIPAL }
CLRSCR;
write ('Stabiliti numarul de multimi, n = ');
readln (n);
for i:= 1 to n do
begin
write ('Cate elemente are multimea ',i,' : ');
readln ( nrelem [i] );
end;

27
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
poz := 1;
f [poz] := 0;
while poz > 0 do
begin
if f [poz] < nrelem [poz] then
begin
f [poz] := f[poz] + 1;
if poz = n then
begin
if (NOT VECINI) AND (EXISTA) then

begin
{SCRIE;} {apel optional al acestei proceduri}
SCRIETEXT;
End;
end
else
begin
poz := poz + 1; {PAS INAINTE}
f [poz] := 0
end
end
else
poz := poz – 1 {PAS INAPOI}
end;
readln
end.

ATESTAT - 2003 - 21 - Generarea permutărilor de n elemente, n > 0.

Rezolvare:
Aplicând algoritmul BACKTRACKING, vom genera permutările de ordinul n în variantă iterativă.
Program ATESTAT_2003_21_PERMUTARI_ITERATIV;
uses crt;
const
nmax = 100;
type
vector = array [1..nmax] of integer;
var
f : vector;
sol, n, i : integer;
procedure VERIFICA ( k : integer; f : vector ; VAR CONTIN : boolean );
LABEL
10;
begin
CONTIN := TRUE;
for i := 1 to k - 1 do
begin
if f [i] = f [k] then
begin
CONTIN := FALSE;
GOTO 10
end;
end;
10:
end;

28
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
procedure SCRIE ;
begin
sol := sol + 1;
write ('Solutia nr. ',sol,' ');
for i := 1 to n do
begin
write ( f [i] : 3 )
end;
writeln
end;

procedure PERMUTA ( m : integer );


LABEL
20;
var
poz : integer;
CONTIN : boolean;
begin
poz := 1;
f [poz] := 0;

while poz > 0 do


begin
CONTIN := FALSE;
while f [poz] < m do
begin
f [poz] := f [poz] + 1;
VERIFICA (poz, f, CONTIN);
if CONTIN = TRUE then
GOTO 20
end; {sfarsit WHILE interior}

20: if ( CONTIN = TRUE ) AND (poz = n) then


SCRIE;
if ( CONTIN = TRUE ) and (poz < n) then
begin
poz := poz + 1; {PAS INAINTE}
f [poz] := 0
end;
if CONTIN = FALSE then
poz := poz – 1 {PAS INAPOI}

end; {sfarsit WHILE exterior}


end; {sfarsit procedura PERMUTA}

Begin { PROGRAM PRINCIPAL }


clrscr;

sol := 0;

write('Dati n = ');
readln (n);

writeln;

PERMUTA (n);

if sol = 0 then
writeln ('Nu exista solutie');

readln
end.

29
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ATESTAT - 2003 - 22 - Să se afişeze termenii şirului lui Fibonacci, pentru un “n” dat.

Rezolvare:
Termenii şirului vor fi reţinuţi într-un tablou ”FIBO”. Generarea termenilor se va face în variantă
iterativă.
Program ATESTAT_2003_22 ;
CONST
nmax = 100;
TYPE
vector = array [1..nmax] of integer;
VAR
FIBO : vector;
n, i : integer;

Begin { PROGRAM PRINCIPAL }


write ('Dati numraul de termeni, n = ');
readln (n);
FIBO [1] := 1;
FIBO [2] := 1;

for i := 3 to n do
begin
FIBO [i] := FIBO [i-1] + FIBO[i-2];
end;
for i := 1 to n do
begin
writeln ( FIBO [ i ] ,' = ', FIBO [ i ] )
end;
readln
end.

ATESTAT - 2003 - 23 - Fie “A” un şir cu n elemente întregi, n > 0. Să se ordoneze crescător
folosind metoda bulelor.

Rezolvare:

 Definim procedura ORDONEAZA, bazată pe algoritmul de sortare BUBBLE-SORT.


 Definim procedura TIPARESTE, care afişează vectorul sortat.
Program ATESTAT_2003_23_BUBBLE_SORT ;
uses CRT;
const
nmax = 30;
type
vector = array [1..nmax] of integer;
var
a : vector;
i, n : integer;
procedure ORDONEAZA (var x:vector; m:integer);
var
k, j, aux: integer;
begin
repeat
k:= 0;
j := 1;

30
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
repeat
if x[j] < x [j+1] then
begin
aux := x[j];
x[j] := x[j+1];
x[j+1] := aux;
k := 1
end;
j := j + 1
until (j > m - 1)
until (k = 0);
end;

procedure TIPARESTE (x:vector; m:integer);


begin
for i := 1 to m do
begin
writeln ('x [i] = ', x [i])
end
end;

Begin { PROGRAM PRINCIPAL }


clrscr;
write ('Introduceti n = ');
readln (n);
writeln;

for i := 1 to n do
begin
write ('a [i] = ');
readln (a [i] )
end;
writeln;
readln;
clrscr;
writeln;

ORDONEAZA (a, n);

TIPARESTE (a, n);

writeln;
readln
end.

ATESTAT - 2003 - 24 - Fie A şi B doi vectori cu câte m, respectiv n elemente numere întregi
(m > 0, n > 0), ordonaţi crescător. Să se interclaseze, în vectorul C, vectorii A şi B.

Rezolvare:
Program ATESTAT_2003_24_INTERCLASARE ;
uses CRT;
CONST
nmax = 50;
TYPE
vector = array [1..nmax] of integer;
vectortot = array [1..2*nmax] of integer;

31
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
var
m, n, i, j, k : integer;
A, B : vector;
C : vectortot;

Begin { PROGRAM PRINCIPAL }


clrscr;
write ('Dati numarul de elemente ale vectorului a, m = ');
readln (m);

write ('Dati numarul de elemente ale vectorului b, n = ');


readln (n);
writeln;
writeln ('Dati primul vector SORTAT :');
writeln;
for i := 1 to m do
begin
write ('A [',i,'] = ');
readln ( A [i] );
end;
writeln;
writeln ('Dati al doilea vector SORTAT');
writeln;
for j := 1 to n do
begin
write ('B [',j,'] = ');
readln (B [j]);
end;

k := 0;

i := 1;
j := 1;

WHILE (i <= m) AND (j <= n) do


begin
if A [i] <= B [j] then
begin
k := k + 1;
C [k] := A [i];
i := i + 1;
end
else
begin
k := k + 1;
C [k] := B [j];
j := j + 1;
end;
end;

WHILE i <= m do
begin
k := k + 1;
C [k] := A [i];
i := i + 1
end;

WHILE j <= n do
begin
k := k + 1;
C [k] := B [j];
j := j + 1
end;

32
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
writeln;
writeln ('Vectorul rezultat in urma interclasarii este:');
writeln;

for k := 1 to m + n do
begin
writeln ('C [',k,'] = ', C [k] );
end;

readln
end.

ATESTAT - 2003 - 25 - Fie X un vector ordonat cu “n” elemente numere întregi, n > 0 şi “elem” o
valoare întreagă, citită de la tastatură. Să se decidă dacă “elem” se găseşte în vectorul X, folosind
metoda Divide et Impera.

Rezolvare:
Program ATESTAT_2003_25_Cautare_Binara_Recursiva ;
uses CRT;
type
vector = array [1..20] of integer;
VAR
x : vector;
elem, n, i : integer;
GASIT : boolean; {GASIT = TRUE daca elementul a fost gasit si FALSE daca nu}

procedure CAUTA ( incep, sf : integer; VAR GASIT : boolean );


var
m : integer;
begin
IF incep <= sf then
begin
m := (incep + sf) DIV 2;
if elem = x [m] then
GASIT := true
else
if elem < x [m] then
CAUTA ( incep, m-1, GASIT)
else
CAUTA (m+1, sf, GASIT)
end
ELSE
GASIT := false
end; {sfarsit procedura}

Begin { PROGRAM PRINCIPAL }


CLRSCR;
write ('n = ');
readln (n);

for i := 1 to n do
begin
write ('x [ ',i,' ] = ');
readln (x[i]);
end;

33
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
writeln;
write ('Dati elementul cautat, elem = ');
readln (elem);

CAUTA (1, n, GASIT);

if GASIT = true then


writeln (elem,' exista')
else
writeln (elem,' nu exista');
readln
end.

ATESTAT - 2003 - 26 - Fie n numere întregi a1, a2, ... an, cu n > 0. Să se determine CMMDC al
celor n numere, prin metoda DEI.
Rezolvare:
Prin metoda DEI (Divide-Et-Impera) se determină CMMDC pentru prima jumătate a vectorului, apoi
pentru cea de-a doua jumătate, după care vom reuni rezultatele.
Program ATESTAT_2003_26_CMMDC_DEI ;
CONST
nmax = 100;
TYPE
vector = array [1..nmax] of integer;
VAR
x : vector;
C, n, i : integer;

function CMMDC (A, B : integer) : integer;


var
aux, R : integer;
begin
if A < B then
begin
aux := A;
A := B;
B := aux
end;
R := A MOD B;
while R <> 0 do
begin
A := B;
B := R;
R := A MOD B
end;
CMMDC := B
end; { sfarsit functie CMMDC }

function DIVCOM (incep, sf : integer): integer;


{ determina CMMDC prin DEI }
VAR
mij, C1, C2 : integer;
begin
if incep = sf then
DIVCOM := x [incep]
else
begin
if sf - incep = 1 then
DIVCOM := CMMDC ( x [incep], x [sf] )

34
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
else
begin
mij := (incep + sf) DIV 2;
C1 := DIVCOM (incep, mij);
C2 := DIVCOM (mij + 1, sf);
DIVCOM := CMMDC (C1, C2)
end
end
end; { sfarsit functie DIVCOM }
Begin { PROGRAM PRINCIPAL }
write ('Dati nr. de elemente ale vectorului, n = ');
readln (n);
for i:= 1 to n do
begin
write ('Dati x [ ', i,' ] = ');
readln (x [i])
end;
C := DIVCOM (1, n);
writeln ('C = ', C);
readln
end.

ATESTAT - 2003 - 27 - Fie “A” un şir cu n numere întregi, n > 0. Să se ordoneze crescător
folosind metoda sortării prin numărare.

Rezolvare:
Descrierea metodei:
Iată o situaţie concretă: la ora de educaţie fizică elevii trebuie să se aşeze în ordinea crescătoare a
înălţimii. Fiecare elev va număra câţi colegi sunt mai mici ca înălţime decât el. Astfel, dacă un elev
“E” va şti că are 15 colegi mai mici decât el, atunci elevul “E” se va aşeza pe poziţia 16.
Metoda de sortare prin numărare constă în următoarele:
 Fie A un vector cu n elemente. Se va crea un vector NR astfel încât :
NR [i] = "numărul de valori din A mai mici decât A[i]".
 Folosim un vector auxiliar C, în care vom prelua elementele sortate ale vectorului A. Fiecare
element A[i] va fi trecut în C în poziţia NR [i] + 1. Pentru exemplul de mai sus, pentru elevul “E”,
NR [i] = 15, iar poziţia pe care trebuie s-o ocupe “E” în vectorul sortat va fi 16, deci NR [i] + 1.

Program ATESTAT_2003_27_SORTARE_PRIN_NUMARARE ;
uses CRT;
const
nmax = 100;
type
vector = array [1..10] of integer;
var
A: vector;
i, n: integer;
procedure CITIRE (var A: vector; n: integer);
var
i:integer;
begin
for i:=1 to n do
begin
write ('Dati A [' , i, '] = ');
readln (A [i]);
end;
end;

35
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
procedure AFISARE (v: vector; m: integer);
begin
for i := 1 to m do
begin
writeln ('A [ ', i, ' ] = ', v [i])
end
end;
procedure ORDONARE (var A: vector; n: integer);
var
NR, C: vector;
j, i: integer;
begin
{Pentru fiecare element A[i] se numără în A câte elemente sunt mai mici
decât A [i]; numărul obţinut în urma numărării se trece în NR [i]}
for i := 1 to n do
NR [i] := 0;
for i := 2 to n do
begin
for j := 1 to i - 1 do
begin
if A [i] > A [j] then
NR [i] := NR [i] + 1
ELSE
NR [j] := NR [j] + 1;
End; { sfârşit for interior}
end; {sfârşit for exterior}

{Vom crea vectorul temporar C, în care se reţin elementele în ordine crescătoare,


şi apoi îl vom copia în A. Dacă A [i] are NR[i] elemente mai mici decât el,
atunci, în vectorul ordonat, A [i] va fi în poziţia NR [i] + 1}.

for i := 1 to n do
C [ NR [i] + 1 ] := A [i];

{copiem în A elementele lui C}


for i:=1 to n do
A [i] := C [i];
end; {sfarsit procedura ORDONARE}

Begin { PROGRAM PRINCIPAL }


clrscr;
write ('Dati numarul de elemente ale vectorului, n = ');
readln (n);
CITIRE (A, n);
ORDONARE (A, n);
AFISARE (A, n);
end.

ATESTAT - 2003 - 28 - Să se citească din fişierul VEC.TXT, vectorul “V” de întregi şi să se


calculeze apoi media aritmetică a elementelor pozitive.

Rezolvare:
Atenţie ! Fişierul VEC.TXT trebuie să existe pe discul C: şi să conţină valori. Dacă nu există, îl
vom crea, ca mai jos, după care îl vom accesa, citind din el întregi, în condiţiile problemei.
Program ATESTAT_2003_28 ;
VAR
f : file of integer;
Spoz, poz, x, v, n, i : integer;
Med : real;
36
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Begin { PROGRAM PRINCIPAL }
ASSIGN (f, 'C:\VEC.TXT');
rewrite (f);

{ CREAREA lui VEC.TXT }


write ('Dati numarul de intregi din fisier, n = ');
readln (n);
writeln ('Introduceti elementele fisierului (pozitive si negative) ');

for i := 1 to n do
begin
write ('Dati un intregul al ', i, ' lea x = ');
readln (x);
write (f, x);
end;

RESET (f); {pregatire fisier pentru citire}


Spoz := 0; { initializare suma pozitive }
poz := 0;

while not EOF (f) do


begin
READ (f, v); { citesc o componenta din f }
if v > 0 then
begin
poz := poz + 1;
Spoz := Spoz + v;
end;
end;
if poz > 0 then
begin
Med := Spoz / poz;
writeln ('Media pozitivelor = ', Med);
end
else
writeln ('Nu exista numere pozitive');
readln
end.

ATESTAT - 2003 - 29 - Să se calculeze maximul elementelor matricii A (m, n) şi să se adauge la


sfârşitul fişierului text MAT.TXT.

Rezolvare: Vom folosi un algoritm cunoscut pentru determinarea maximului dintr-un şir de numere.
Program ATESTAT_2003_29 ;
CONST
nmax = 30;
TYPE
matrice = array [1..nmax, 1..nmax] of real;
VAR
A : matrice;
f : file of real;
m, n, i, j : integer;
x, Max : real;
Begin { PROGRAM PRINCIPAL }
ASSIGN (f, 'C:\MAT.TXT');
rewrite (f);
repeat
write ('Dati m = ');
readln (m)
until (m >= 1) AND (m <= nmax);

37
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
repeat
write ('Dati n = ');
readln (n)
until (n >= 1) AND (n <= nmax);
writeln ('Dati matricea');
for i := 1 to m do
begin
for j := 1 to n do
begin
write ('Dati A [ ', i,',', j, ' ] = ');
readln ( A [i, j]);
end;
end;
max := A [1,1];
for i := 1 to m do
begin
for j := 1 to n do
begin
if max < A [i, j] then
Max := A [i, j]
end;
end;
writeln ('Max = ', Max);
RESET (f);
while not EOF (f) do
begin
read (f, x)
end;
write (f, max);
RESET (f);
READ (f, x);
Max := x;
writeln ('Max citit din fisier este = ', max);
readln
end.

ATESTAT - 2003 - 30 - Să se scrie la sfârşitul fişierului text DIV.TXT toţi divizorii naturali ai
numărului întreg x.

Rezolvare: Folosim algoritmul de verificare a primalităţii unui număr întreg.


Program ATESTAT_2003_30 ;
VAR
f : file of integer;
x, d, diviz : integer;

Begin { PROGRAM PRINCIPAL }


ASSIGN (f, 'C:\DIV.TXT');
rewrite (f);
write ('Dati x = ');
readln (x);
x := ABS (x); {daca x este negativ il facem > 0 }
diviz := 1;
while diviz <= x do
begin
if x MOD diviz = 0 then
write ( f, diviz );
diviz := diviz + 1
end;

38
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
RESET (f);
writeln ('Citim fisierul');
while not EOF (f) do
begin
read (f, d);
writeln ('Divizor = ', d)
end;
readln
end.

ATESTAT - 2003 - 31 - Să se determine toate modalităţile de plată a unei sume S (S >= 0 şi


S <= 1.000.000) cu bancnote de valoare dată: b1 = 1000, b2 = 5000, b3 = 10.000, b4 = 100.000.

Rezolvare:

Varianta 1
Program ATESTAT_2003_31_Bancnote_1_Platile_unei_sume_BackTracking ;
uses CRT;
VAR
s : array [0..20] of integer;
f, b : array [1..20] of integer;
{f [poz] = numarul de bancnote de tipul b [poz]}
nrsol, Suma, m, poz, i, j : integer; {m = numarul de tipuri de bancnote }
{poz = pozitia unei bancnote in suma}
Begin { PROGRAM PRINCIPAL }
clrscr;
nrsol := 0;
write ('Dati o suma < 1.000.000, Suma = ');
readln (Suma);
write ('Cite tipuri de bancnote folositi, (la noi m = 4) m = ');
readln (m);
for i := 1 to m do
begin
write ('Dati valoarea bancnotei de tipul ',i, ' b [ ',i,' ] =');
readln (b[i])
end;
s[0] := 0;
f[1] := 0;
poz := 1;
while poz > 0 do
begin
while ( poz <= m ) AND ( f[poz] * b[poz] < Suma - s[poz-1] ) do
begin
f[poz] := f[poz] + 1;
s[poz] := s[poz-1] + f[poz] * b[poz];
IF s[poz] = Suma then
begin
if poz > 1 then
begin
nrsol := nrsol + 1;
writeln ('Solutia nr. ',nrsol);
write ( Suma,' = ',f[1],' * ',b[1]);
for j := 2 to poz do
begin
write (' + ', f[j],' * ',b[j])
end;
end
end

39
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ELSE
begin
poz := poz + 1; {PAS INAINTE}
f[poz] := 0; {f [poz] := f[poz-1] - 1; }
end { f[poz] >= f [poz-1] }
end; {sfarsit WHILE interior}
poz := poz-1; {PAS INAPOI}
end; { sfarsit WHILE exterior}
readln
end.

Varianta 2
Program ATESTAT_2003_31_Bancnote_2_Platile_unei_sume_BackTracking;
type
stiva = array[1..100] of longint;
var
st, a, b: stiva;
n, k, s, i: Longint;
as, ev: boolean;

Procedure Init (k: integer; var st : stiva);


begin
st [k] := -1
End;

Procedure Succesor (var as: boolean; var st: stiva; k: integer);


var
s1, i: longint;
begin
if (st[k] < b[k]) and (k <= n) then
begin
s1 := 0;
for i:=1 to k do
s1 := s1 + st[i] * a[i];
as := (s1 < s)
end
else
as := false;
if as then
st[k] := st[k] + 1
End;

Procedure Valid (var ev: boolean; st: stiva; k: integer);


var i: integer;
begin
ev := true
End;

Function Solutie( k:integer): boolean;


var i, s1: longint;
begin
s1 := 0;
for i := 1 to k do
s1 := s1 + st[i]*a[i];
solutie := (s=s1)
End;

Procedure Scrie;
var i: integer;
begin
writeln (s,' lei se platesc cu:');

40
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
for i := 1 to k do
begin
if st [i]>0 then
writeln ( st [i]:2,' de ', a[i],' lei');
end;
writeln ('---------------------------------');
readln
End;

Begin { PROGRAM PRINCIPAL }


n := 4;
a[1] := 1000;
a[2] := 5000;
a[3] := 10000;
a[4] := 100000;

write ('Suma = '); readln (s);

for i := 1 to n do
begin
b[i] := s div a[i]
end;
k := 1;
Init (k, st);
while (k > 0) do
begin
repeat
succesor (as, st, k);
if as then
valid (ev, st, k);
until (not as) or (as and ev);
if as then
if solutie (k) then
SCRIE
else
begin
k := k+1;
init (k, st);
end
else
k := k-1
end;
readln
END.

ATESTAT - 2003 - 32 - Să se parcurgă, prin săritura calului, o tablă de şah, netrecând de două ori
prin aceleaşi poziţii sau omiţând o anumită poziţie.

Rezolvare:
Program ATESTAT_2003_32_SARITURA_CALULUI ;
uses CRT;
CONST
mmax = 8; { nr. de linii }
nmax = 8; { nr. de coloane }
TYPE
matrice = ARRAY [1..mmax, 1..nmax] of integer; { matricea TABLEI DE SAH }

41
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
VAR
SOL : matrice; { SOL = matricea solutiilor }
{ SOL [i, j] = 0 daca nu s-a trecut prin pozitia (i, j) }
{ <> 0 daca s-a trecut prin pozitia (i, j) }

m, n, nrsol, i, j : integer; { (i, j) = pozitia pe tabla de sah }


procedure SCRIE;
begin
writeln;
writeln ('Apasati o tasta ');
writeln;

readln;

nrsol := nrsol + 1;

writeln ('Solutia ', nrsol, ' : ');


writeln;

for i := 1 to m do
begin
for j := 1 to n do
begin
write ( ' ', SOL [i, j] : 3,' ');
end;
writeln;
writeln;
end;

readln;

CLRSCR
end; { sfarsit procedura SCRIE }

procedure TRASEU (i, j, pas : integer);


begin
IF (i IN [1..m])
AND (j IN [1..n]) then
begin
if SOL [i, j] = 0 then
begin
SOL [i, j] := pas ;

if pas = m * n then

SCRIE

else
begin
TRASEU (i-2, j+1, pas + 1 );
TRASEU (i-1, j+2, pas + 1 );
TRASEU (i+1, j+2, pas + 1 );
TRASEU (i+2, j+1, pas + 1 );
TRASEU (i+2, j-1, pas + 1 );
TRASEU (i+1, j-2, pas + 1 );
TRASEU (i-1, j-2, pas + 1 );
TRASEU (i-2, j-1, pas + 1 );
end;
SOL [i, j] := 0;
end;
end;
end; { sfarsit procedura }

42
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
Begin { PROGRAM PRINCIPAL }
CLRSCR;
write ('Dati numarul de linii ( cel putin 5), m = ');
readln (m);
write ('Dati numarul de coloane ( egal cu numarul de linii ), n = ');
readln (n);

for i := 1 to m do
begin
for j := 1 to n do
begin
SOL [i, j] := 0
end;
end;
nrsol := 0;
CLRSCR;

TRASEU (1, 1, 1);

if nrsol = 0 then
writeln ('Nu exista solutie');
writeln;

readln
END.

ATESTAT - 2003 - 33 - Să se parcurgă în lăţime un graf neorientat.

Rezolvare:

Varianta 1: Algoritmul este descris în lucrarea Cătălin Tănase – Note de curs, Ediţia II, 2008.
Program ATESTAT_2003_33_Parcurgere_graf_in_latime_BF_Breadth_First ;
uses CRT;
VAR
VIZITAT : array [1..20] of 0..1;
{elementele vectorului VIZITAT sunt: }
{ = 1, daca un varf a fost vizitat}
{ = 0, in caz contrar}
A : array [1..20, 1..20] of integer; { A = matricea de adiacenta}

n : integer; { n = nr. de noduri }


m : integer; { m = nr. de muchii }

i, j : integer ; { i, j = indecsi }
v : integer; { v = varf curent }
x, y : integer; { x, y = extremitati ale unei muchii}
prim, ultim : integer;
{ pointeri catre "primul" / "ultimul" elem. al cozii}

C : array [1..20] of integer;


{ C = coada in care depunem varfurile nevizitate, vecine ale unui varf }
begin
CLRSCR;
writeln;
write ('Dati numarul de varfuri, n = ');
readln (n);
writeln;

43
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
write ('Dati numarul de muchii, m = ');
readln (m);
writeln;
for i := 1 to n do
begin
for j := 1 to n do
begin
A [i, j] := 0 {initializare elemente matrice de adiacenta cu 0}
end;
end;
writeln;
writeln ('Dati extremitatile muchiilor');
writeln;
for i := 1 to m do
begin
writeln ('Pentru muchia ', i,', dati extremitatile');
write ('Prima extremitate, x = ');
readln (x);
write ('A doua extremitate, y = ');
readln (y);
writeln;
A [x, y] := 1;
A [y, x] := 1;
end;
writeln;

write ('Dati varful de plecare, i = ');


readln (i);
writeln;

C [1] := i; {primul element din coada este varful de plecare}

for j := 1 to n do
begin
VIZITAT [j] := 0;
end;

prim := 1; {pointare catre primul element al cozii}


ultim := 1; {pointare catre ultimul element al cozii}

VIZITAT [i] := 1;

while prim <= ultim do


begin
v := C [prim] ;
for j := 1 to n do
begin
if (A [v, j] = 1) AND (VIZITAT [j] = 0) then
begin

ultim := ultim + 1;
{se depune un varf in coada in pozitia "ultim"}

C [ ultim ] := j;

VIZITAT [ j ] := 1;

end; {end IF }
end; {end FOR }

prim := prim + 1;

end; {end WHILE}

44
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
writeln ('Lista nodurilor, in parcurgere BF, plecand din nodul ', i,', este :');
for j := 2 to ultim do
begin
write ( C [j],' ');
end;
readln
end.

Varianta 2:

Program ATESTAT_2003_33_Parcurgere_graf_in_latime_cu_procedura_recursiva ;

type mat = array [1..20, 1..20] of integer;


vect = array [1..20] of integer;
var v : mat;
t, coada : vect;
n, k, j, i, p : integer;

procedure PBF (i:integer); { Parcurgere “Breadth First” }


{procedura recursiva}
var j : integer;
begin
for j:=1 to n do
if ( v [coada [i],j] = 1 ) and ( t [j] = 0) then
begin
k := k+1;
coada [k] := j;
t[j] := 1 ;
end;
if i<n then
PBF (i+1);
end;

Begin { PROGRAM PRINCIPAL }


write('n = ');
readln(n);
for i := 1 to n do
begin
t[i] := 0;
for j := i+1 to n do
begin
write ('Legatura intre ',i,' si ',j,' = ');
readln (v[i,j]);
v[j,i] := v[i,j];
end;
end;
write ('Dati Nodul de plecare, p = ');
readln (p);

coada [1] := p;
t[p] := 1;
k := 1;

PBF (p);

for i:=1 to n do
write (coada[i],'->');

writeln;
readln
end.

45
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ATESTAT - 2003 - 34 - Să se determine un ciclu într-un graf astfel încât să se treacă prin toate
punctele grafului, iar costul drumului să fie minim.

Rezolvare: Se foloseşte algoritmul cunoscut de determinare a unui ciclu într-un graf.


Program ATESTAT_2003_34_Graf_cost_minim ;
var
A: array [1..20,1..20] of integer; {matricea de adiacenta}
s: array [1..20] of integer;
n, i, j, v, v1, v2, min, cost: integer;

Begin { PROGRAM PRINCIPAL }


Write ('Dati numarul de noduri, n = ');
Readln (n);

writeln (‘Dati matricea de adiacenta A’);


for i := 1 to n - 1 do
for j := i + 1 to n do
begin
write ('Dati A [ ', i, ', ',j,' ] = ');
readln ( A [i, j]);
A [j, i] := A [i, j]
end;
for i:=1 to n do
begin
S [i] := 0; {matricea de adiacenta este patratica, avand toate}
A [i, i]:= 0 {elementele diagonalei principale egale cu zero }
end;

write ('Dati Nodul de pornire, v = ');


readln (v);

S [v] := 1;
v2 := v;
cost := 0;
writeln (v);

for i := 1 to n-1 do
begin
min := 30000;
for j := 1 to n do
if (A [v2, j] <> 0) and ( S [j] = 0) and ( min > A [v2, j]) then
begin
min := A [i, j];
v1 := j
end;
v2 := v1;
S [v2] := 1;
cost := cost + min;
write (v1, ' -> ');
end;
cost := cost + A [v2, v];
writeln (v);
writeln ('Cost total = ',cost);
readln
end.

46
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
ATESTAT - 2003 - 35 - Să se afişeze toate posibilităţile de aranjare pe o casetă a “n” melodii,
codificate cu numere de la 1 la n, astfel încât melodia X să urmeze după melodia Y (x şi y sunt două
valori citite). Se consideră n < 10.

Rezolvare:
Program ATESTAT_2003_35_Caseta_cu_melodii ;
uses crt;
const nmax = 100;
type vector = array [1..nmax] of integer;
var f : vector;
SOLUTII : TEXT; {fisier text de pe disc in care vom retine solutiile}
sol, n, i, x, y : integer;

procedure VERIFICA ( k : integer; f : vector ; VAR CONTIN : boolean );


LABEL 10;
begin
CONTIN := TRUE;
for i := 1 to k - 1 do
begin
if f [i] = f [k] then
begin
CONTIN := FALSE;
GOTO 10
end;
end;
10: end;

procedure SCRIE ;
begin
sol := sol + 1;
write ('Solutia nr. ',sol,' ');
for i := 1 to n do
begin write ( f [i] : 3 ); write (SOLUTII, f [i] : 3 ); end;
writeln (SOLUTII); writeln {Linie de spatiere}
end;

function POZMELODIE (x, y : integer) : BOOLEAN;


Var OK : boolean;
begin
OK := FALSE;
for i := 1 to n - 1 do
begin
if (f [i] = y) AND ( f [ i + 1 ] = x ) then
OK := TRUE;
end;
POZMELODIE := OK
end;

procedure PERMUTA ( m : integer );


LABEL 20;
var k : integer;
CONTIN : boolean;

47
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
begin
k := 1;
f [k] := 0;
while k > 0 do
begin
CONTIN := FALSE;
while f [k] < m do
begin
f [k] := f [k] + 1;
VERIFICA (k, f, CONTIN);
if CONTIN = TRUE then
GOTO 20
end; {sfarsit WHILE interior}
20: if ( CONTIN = TRUE ) AND (k = n) then
begin
if POZMELODIE (x, y) = TRUE then
SCRIE;
end;
if ( CONTIN = TRUE ) and (k < n) then
begin
k := k + 1; {PAS INAINTE}
f [k] := 0
end;
if CONTIN = FALSE then
k := k - 1 {PAS INAPOI}
end; {sfarsit WHILE exterior}
end; {sfarsit procedura PERMUTA}

Begin { PROGRAM PRINCIPAL }


clrscr;
assign (SOLUTII, 'C:\SOLUTII.txt');
{Solutiile se vor scrie si in fisierul C:\SOLUTII.TXT}
rewrite (SOLUTII);
sol := 0;
write('Dati nr. de melodii ( < 10 ) n = ');
1 2 4 3 5
readln (n); 1 2 5 4 3
write ('Dati melodia nr. x = '); 1 4 3 2 5
readln (x); 1 4 3 5 2
write ('Dati melodia nr. y = '); 1 5 2 4 3
readln (y);
1 5 4 3 2
writeln; 2 1 4 3 5
2 1 5 4 3
PERMUTA (n); 2 4 3 1 5
if sol = 0 then
2 4 3 5 1
writeln ('Nu exista solutie'); 2 5 1 4 3
readln 2 5 4 3 1
end. 4 3 1 2 5
4 3 1 5 2
De exemplu, pentru n = 5 4 3 2 1 5
X=3 4 3 2 5 1
Y=4 4 3 5 1 2
se vor afişa pe ecran 4 3 5 2 1
(respectiv se vor scrie în fişierul C:\SOLUTII.TXT) 5 1 2 4 3
soluţiile: 5 1 4 3 2
5 2 1 4 3
5 2 4 3 1
5 4 3 2 1

48