Vous êtes sur la page 1sur 92

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

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.

4
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;
5
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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 }

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

7
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

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

9
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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”.

10
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')

11
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

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


13
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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.

14
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.
15
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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;

16
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
17
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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';

18
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.

19
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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:
20
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
21
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

22
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
23
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

24
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;
25
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

26
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.

27
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

28
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 = ');
29
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

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

31
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

32
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;
33
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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;

34
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).
35
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
 Î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;

36
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.

37
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

38
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.

39
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

40
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;
41
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

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

43
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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

44
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

45
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

46
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
47
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

48
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

49
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

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

51
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

52
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;
53
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

54
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;
55
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

56
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.

57
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

58
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
59
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

60
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
61
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

62
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
63
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

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

65
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 }

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

66
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

67
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

68
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];

69
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

70
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.
71
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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

72
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.

73
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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;

74
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_Bac
kTracking ;
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 = ');
75
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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

76
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_Bac
kTracking;
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
77
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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:');

78
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
79
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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 }

80
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
81
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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 }

82
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_Bre
adth_First ;

83
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

84
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}
85
Probleme rezolvate de programare – Subiecte propuse la ATESTAT

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}

86
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_pro
cedura_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

87
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

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

89
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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.

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


91
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
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;

92
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}

93
Probleme rezolvate de programare – Subiecte propuse la ATESTAT
rewrite (SOLUTII);
sol := 0;
write('Dati nr. de 1 2 4 3 5
melodii ( < 10 ) n = '); 1 2 5 4 3
readln (n); 1 4 3 2 5
write ('Dati melodia nr. 1 4 3 5 2
x = ');
1 5 2 4 3
readln (x);
write ('Dati melodia nr. 1 5 4 3 2
y = '); 2 1 4 3 5
readln (y); 2 1 5 4 3
2 4 3 1 5
writeln;
2 4 3 5 1
PERMUTA (n); 2 5 1 4 3
2 5 4 3 1
if sol = 0 then 4 3 1 2 5
writeln ('Nu exista 4 3 1 5 2
solutie');
readln 4 3 2 1 5
end. 4 3 2 5 1
4 3 5 1 2
De exemplu, pentru n = 5 4 3 5 2 1
X=3 5 1 2 4 3
Y=4 5 1 4 3 2
se vor afişa pe ecran 5 2 1 4 3
(respectiv se vor scrie în fişierul 5 2 4 3 1
C:\SOLUTII.TXT) 5 4 3 2 1
soluţiile:

94

Vous aimerez peut-être aussi