Documente Academic
Documente Profesional
Documente Cultură
Olimpiada Republicană
la Informatică
(EDIŢIA 2003)
Chişinău, 2003
Olimpiada Republicanã la Informaticã. Ediþia 2003. Chiºinãu: Editura
ASEM, 2003. –64 p.
Colegiul de redacþie:
2
CUPRINS
Cuvînt înainte 5
1. Ziua 1
Clasele 7-9 8
Calcule 9
Cifru 11
Domino 15
Clasele 10-12 20
Calcule 21
Cifristul 23
Domino 27
2. Ziua 2
Clasele 7-9 35
Votul 36
Metroul 40
Roboþii 45
Clasele 10-12 48
Votul 49
Metroul 53
Cina 59
3
4
Dragi elevi,
Stimaþi profesori,
Informatica ne schimbã viaþa, uneori într -un mod
într-un
cu totul neaºteptat chiar ºi pentru cei iniþiaþi în domeniu.
Pentru a stãpîni schimbarea, pentru a fi competitivi, pentru
a beneficia din roadele acestei ºtiinþe, trebuie sã cunoaºtem
ºi sã putem aplica întregul arsenal de metode ºi tehnici
informaþionale studiate în ºcoalã.
Olimpiadele R epublicane la Informaticã au drept
Republicane
scop suprem atragerea elevilor în competiþii deschise ºi
oneste, educarea culturii informaþionale ºi a gîndirii
algoritmice, focalizarea interesului public pe tehnologiile
de vîrf
vîrf,, atragerea tineretului studios în domeniile de
perspectivã, atît în ºtiinþã, cît ºi pe piaþa muncii.
Sînt sigur cã pe parcursul competiþiilor
competiþiilor,, elevii ºi
profesorii au iniþiat noi colabor
colaborãã ri, au descoperit metode
originale de predare-învãþare, au ffãcut
ãcut un util schimb de
experienþã. Am cîºtigat noi cu toþii, cei care iubim atît
de mult Informatica.
Mulþumim din suflet tuturor participanþilor la
Olimpiadã pentru activismul manifestat ºi le dorim mari
succese în viitor
viitor..
În numele Consiliului Olimpic la Informaticã,
Anatol Gremalschi,
doctor habilitat,
profesor universitar, UTM
5
Ministerul Educaţie al Republicii Moldova
Instrucţiune
I. Fiºiere ºi directoare
I.1. Dupã terminarea lucrului, participantul va transmite oficialului numai fiºierele sursã
ale programelor, câte unul pentru fiecare problemã.
I.2. Fiºierele sursã vor avea acelaºi nume ca ºi fiºierele de intrare/ieºire. De exemplu în
cazul fiºierelor de intrare/ieºire numite SORTARE.IN ºi SORTARE.OUT, fiºierul sursã
se va numi SORTARE.PAS, SORTARE.C, sau SORTARE.CPP.
I.3. Fiºierele sursã se vor afla într-un director cu numele format din primele 7 litere ale
numelui de familie, plus prima literã a numelui. De exemplu pentru elevul Tudor
Mãrgineanu, directorul se va numi MARGINET. Pentru elevul Tudor Roºu, directorul se
va numi ROSUT. Denumirile de directoare sînt indicate în fiºa de înregistrare.
II.1. Programul va citi ºi va scrie toate datele din fiºierele text indicate, cu excepþia
cazurilor în care se indicã altfel în enunþul problemei.
6
III. Limbaje de programare
III.1. Programul va utiliza numai mijloacele standard ale limbajului respectiv, evitându-se
includerea codului Asamblor, codului de maºinã, apelurilor de întreruperi, scrierea în
porturi, schimbarea timpului curent, scrierea directã în memorie, apelul altor programe,
funcþii ale sistemului de operare ºi altor posibilitãþi nestandard.
III.2. Programul Pascal va utiliza numai unit-ul system care este încãrcat de compilator
automat. Includerea altor unit-uri prin utilizarea clausei uses este interzisã, cu excepþia
cazurilor special prevãzute în enunþul problemei.
III.3. Soluþiile competitorilor nu vor include nici un fel de directive de compilare care
altereazã opþiunile prestabilite de compilare.
III.4. Competitorilor le vor fi puse la dispoziþie fiºierele C_PAS.BAT, C_CPP.BAT care vor
compila soluþiile lor cu exact aceleaºi opþiuni ca ºi în cadrul evaluãrii. Mediile integrate
vor fi configurate pentru a reflecta cât mai precis opþiunile de compilare din cadrul
evaluãrii.
IV.2. În cazul încãlcãrii cerinþelor de mai sus, participantul poate fi sancþionat cu anularea
rezultatului pentru problema în cauzã, pentru ziua respectivã, sau cu înlãturarea de la
competiþie.
7
Ziua 1
Clasele 7-9
Descrierea problemelor
Numărul de Denumirea
Denumirea Denumirea Denumirea
puncte alocat fişierului de
problemei fişierului sursă fişierului de ieşire
problemei intrare
CALCULE.PAS
Calcule 100 CALCULE.C CALCULE.IN CALCULE.OUT
CALCULE.CPP
CIFRU.PAS
Cifru 100 CIFRU.C CIFRU.IN CIFRU.OUT
CIFRU.CPP
DOMINO.PAS
Domino 100 DOMINO.C DOMINO.IN DOMINO.OUT
DOMINO.CPP
Total 300 - - -
8
Calcule din antichitate
<Cifră> := I
<Număr> := <Cifră><Număr><Cifră>
<Semn> := +-
<Expresie> := <Număr><Număr><Semn><Expresie>
Exemple:
Numere Expresii
I III
III II-III
IIIIIIIIIII I+I-III+IIIIIII
Date de intrare.
Fiºierul text CALCULE.IN conþine pe o singurã linie un ºir de caractere –
expresia supusã evaluãrii.
Date de ieºire.
Fiºierul text CALCULE.OUT va conþine pe o singurã linie un numãr întreg zecimal
– rezultatul evaluãrii expresiei din fiºierul de intrare.
Exemplu.
CALCULE.IN CALCULE.OUT
I+I-III+IIIIIII 6
Restricþii.
O expresie poate include cel mult 250 de caractere. Timpul de execuþie nu va
depãºi 1 secundã. Fiºierul sursã va avea denumirea CALCULE.PAS,
CALCULE.C sau CALCULE.CPP.
9
Rezolvare
Program Calcule;
{ Clasele 7-9 }
var Expresie : string;
Intrare, Iesire : text;
function Evaluare(Expresie:string):integer;
var v : integer; { valoarea curenta a expresiei}
i : 1..256; { pozitia caracterului curent
in expresie }
Semn : char;
begin
v:=0;
Semn:=’+’;
for i:=1 to length(Expresie) do
case Expresie[i] of
’I’: if Semn=’+’ then v:=v+1 else v:=v-1;
’+’: Semn:=’+’;
’-’: Semn:=’-’;
end;
Evaluare:=v;
end; { Evaluare }
begin
assign(Intrare, ’CALCULE.IN’);
reset(Intrare);
readln(Intrare, Expresie);
close(Intrare);
assign(Iesire, ’CALCULE.OUT’);
rewrite(Iesire);
writeln(Iesire, Evaluare(Expresie));
close(Iesire);
end.
10
Cifru
Fig. 1.
În procesul cifrãrii, Vasilicã înscrie mesajul iniþial în tabel, cîte un caracter în fiecare
celulã, de sus în jos, pe coloane. Dupã completarea primei coloane, se trece la coloana
a doua º.a.m.d., pînã cînd tot mesajul va fi înscris în tabel. Pentru exemplificare, în
tabelul din figurã este înscris mesajul PROGRAMARE. Dupã completarea tabelului,
Vasilicã formeazã mesajul cifrat, copiind în acest scop conþinutul tabelului, celulã dupã
celulã, pe rînduri, rîndurile tabelului fiind selectate într-o anumitã ordine. Ordinea de
explorare a rîndurilor din tabel reprezintã cheia de descifrare, care se anexeazã la
mesajul cifrat. De exemplu, în cazul tabelului din fig. 1 ºi cheia (2, 3, 1), rîndurile vor fi
explorate în ordinea 2, 3 ºi 1, iar mesajul cifrat este
Primind cheia ºi mesajul cifrat, Petricã completeazã un tabel similar, de data aceasta
pe rînduri, de la stînga la dreapta, selectînd ordinea rîndurilor conform cheiei de
descifrare. Dupã completarea tabelului, Petricã copie caracterele din celule, coloanã
dupã coloanã, de sus în jos, obþinînd astfel mesajul iniþial.
Elaboraþi un program care, cunoscînd cheia ºi mesajul cifrat, reconstituie mesajul iniþial.
11
Date de intrare.
Fiºierul text CIFRU.IN constã din trei linii. Pe prima line este înscris numãrul
rîndurilor m. Linia a doua a fiºierului de intrare conþine m numere naturale ce
reprezintã cheia cifrului. Linia a treia conþine un ºir de caractere - mesajul cifrat.
Date de ieºire.
Fiºierul text CIFRU.OUT va conþine pe o singurã linie mesajul descifrat.
Exemplu.
CIFRU.IN CIFRU.OUT
3 PROGRAMARE
2 3 1
RRA OAR PGME
Restricþii.
n ≤ 200. Timpul de execuþie nu va depãºi 1 secundã. Fiºierul sursã va avea
denumirea CIFRU.PAS, CIFRU.C sau CIFRU.CPP.
12
Rezolvare
Program Cifru;
var n,m,t:longint;
A:array[0..400] of char;
B:array[0..200,0..200] of char;
r:array[0..400] of integer;
Result:array[0..400] of char;
num:integer;
procedure Citire;
var f:text;
i:integer;
begin
assign(f,’cifru.in’); reset(f);
readln(f,m);
for i:=1 to m do read(f,r[i]); readln(f);
while not(eoln(f)) do begin t:=t+1;read(f,A[t]);
end;
n:=t div m;
close(f);
end;
procedure Decodificare;
var k,i,j:integer;
begin
k:=1;
for i:=1 to m do
begin
for j:=1 to n do begin B[r[i],j]:=A[k];inc(k);
end;
end;
num:=0;
for j:=1 to n do
for i:=1 to m do
begin num:=num+1; Result[num]:=B[i,j]; end;
while Result[num]=’ ’ do dec(num);
end;
13
procedure Afisare;
var i,j:integer;
f:text;
begin
assign(f,’cifru.out’); rewrite(f);
for i:=1 to num do write(f,Result[i]);
writeln(f);
close(f);
end;
begin
Citire;
Decodificare;
Afisare;
End.
14
Domino
Fig. 1 Fig. 2
Elaboraþi un program care transformã, daca-i posibil, un tren obiºnuit în unul perfect.
Date de intrare.
Fiºierul text DOMINO.IN conþine pe prima linie numãrul de piese n. Urmãtoarele
n linii ale fiºierului de intrare conþin cîte douã numere întregi separate prin spaþiu,
fiecare linie reprezentînd o piesã de domino. Piesele sînt listate în ordinea apariþiei
lor în tren.
Date de ieºire.
Fiºierul text DOMINO.OUT va conþine pe prima linie cuvîntul DA dacã trenul din
fiºierul de intrare poate fi transformat în unul perfect ºi NU în caz contrar. În cazul
rãspunsului DA, urmãtoarele n linii ale fiºierului de ieºire vor conþine cîte douã
numere întregi separate prin spaþiu, fiecare linie reprezentînd o piesã de domino.
Piesele vor fi listate în ordinea apariþiei lor în fiºierul de intrare, astfel încît cele douã
numere de pe pãrþile vecine ale oricãror douã piese adiacente sã fie egale între ele.
15
Exemplu.
DOMINO.IN DOMINO.OUT
4 DA
2 1 1 2
2 6 2 6
5 6 6 5
5 4 5 4
Restricþii.
1 ≤ n ≤ 28. Timpul de execuþie nu va depãºi 1 secundã. Fiºierul sursã va avea
denumirea DOMINO.PAS, DOMINO.C sau DOMINO.CPP.
16
Rezolvare
Vom identifica piesele trenului prin perechile ordonate (ai, bi), i = 1, 2, ..., n. Evident,
operaþia de rotire a piesei i poate fi redatã prin notaþia (ai, bi) → (bi, ai).
Presupunem cã trenul iniþial poate fi transformat în unul perfect. În aceste condiþii sînt
posibile urmãtoarele cazuri:
a) piesa i = 1 ºi-a pãstrat poziþia iniþialã (ai, bi);
b) piesa i = 1 a fost rotitã, avînd în trenul perfect poziþia (bi, ai).
În continuare, vom încerca sã construim trenul perfect pentru cazurile a) ºi b) separat,
rotind, în caz de necesitate, piesele 2, 3, ..., n.
Admitem, cã în procesul examinãrii consecutive a pieselor din componenþa trenului,
piesele i =1, 2, ..., k –1 ºi-au ocupat deja poziþia lor corectã ºi se examineazã piesa k.
Evident, sînt posibile urmãtoarele cazuri:
1) bk-1 = ak. Evident, piesa k ocupã poziþia corectã. Se trece la piesa k + 1.
2) bk-1 = bk. În acest caz piesa k trebuie rotitã: (ak, bk) → (bk, ak). În continuare se
trece la piesa k + 1.
3) bk-1 ≠ ak, bk-1 ≠ bk. Evident, trenul nu poate fi transformat în unul perfect. Stop.
Accentuãm, cã piesa k – 1, care se aflã înaintea piesei curente k, nu mai poate fi
rotitã, întrucît poziþia ei este determinatã de poziþia piesei k – 2, poziþia cãreia, la rîndul
ei, este determinatã de poziþia piesei k – 3 º.a.m.d., pînã la piesa 1.
În programul ce urmeazã, fiecare piesã de domino este reprezentatã cu ajutorul tipului
de date
Piesa = record
a, b : 0..6;
end;
T : array[1..28] of Piesa;
Evident,algoritmulcareverificãcondiþile1)–3)ºiroteºte,încazdenecesitate,
piesele respective, poate fi realizat printr-o singurã parcurgere a tabloului T.
17
Program Domino;
{ Clasele 7-9 }
type Piesa = record
a, b : 0..6;
end;
var T : array[1..28] of Piesa; { trenul }
n : 1..28; { numarul de vagoane in tren }
Perfect : boolean;
c : integer; { variabila de lucru }
procedure Citeste;
{ Citirea datelor din fisierul de intrare }
var i : integer;
Intrare : text;
begin
assign(Intrare, ’DOMINO.IN’);
reset(Intrare);
readln(Intrare, n);
for i:=1 to n do
readln(Intrare, T[i].a, T[i].b);
close(Intrare);
end; { Citeste }
procedure Scrie;
{ Scrierea datelor in fisierul de iesire }
var i : integer;
Iesire : text;
begin
assign(Iesire, ’DOMINO.OUT’);
rewrite(Iesire);
if not Perfect then writeln(Iesire, ’NU’)
else begin
writeln(Iesire, ’DA’);
for i:=1 to n do
writeln(Iesire, T[i].a, ’ ’, T[i].b);
end; { else }
close(Iesire);
end; { Scrie }
18
procedure Transforma;
var j, k : integer;
begin
Perfect:=true;
k:=2;
while ((k<=n) and Perfect) do
begin
if ((T[k-1].b<>T[k].a) and (T[k-1].b<>T[k].b))
then Perfect:=false;
if (T[k-1].b=T[k].b) then
begin
{ rotim piesa T[k] }
j:=T[k].a; T[k].a:=T[k].b; T[k].b:=j;
end; { then }
k:=k+1;
end; { while }
end; { Transforma }
begin
Citeste;
Transforma;
if not Perfect then
begin
{ rotim prima piesa }
c:=T[1].a; T[1].a:=T[1].b; T[1].b:=c;
Transforma;
end; { then }
Scrie;
end.
19
Ziua 1
Clasele 10 - 12
Descrierea problemelor
CIFRIST.PAS
Cifristul 100 CIFRIST.C CIFRIST.IN CIFRIST.OUT
CIFRIST.CPP
DOMINO.PAS
Domino 100 DOMINO.C DOMINO.IN DOMINO.OUT
DOMINO.CPP
Total 300 - - -
20
Calcule din antichitate
<Cifră> := I
<Număr> := <Cifră><Număr><Cifră>
<Semn> := +-
<Expresie> := <Număr><Număr><Semn><Expresie>
Exemple:
Numere Expresii
I III
III II-III
IIIIIIIIIII I+I-III+IIIIIII
Date de intrare.
Fiºierul text CALCULE.IN conþine pe o singurã linie un ºir de caractere –
expresia supusã evaluãrii.
Date de ieºire.
Fiºierul text CALCULE.OUT va conþine pe o singurã linie un numãr întreg zecimal
– rezultatul evaluãrii expresiei din fiºierul de intrare.
Exemplu.
CALCULE.IN CALCULE.OUT
I+I-III+IIIIIII 6
Restricþii.
O expresie poate include cel mult 32000 de caractere. Timpul de execuþie nu va
depãºi 1 secundã. Fiºierul sursã va avea denumirea CALCULE.PAS,
CALCULE.C sau CALCULE.CPP.
21
Rezolvare
begin
assign(Intrare, ’CALCULE.IN’);
reset(Intrare);
n:=0;
while not Eoln(Intrare) do
begin
n:=n+1;
read(Intrare, Expresie[n]);
end;
close(Intrare);
assign(Iesire, ’CALCULE.OUT’);
rewrite(Iesire);
writeln(Iesire, Evaluare);
close(Iesire);
end.
22
Cifristul
Cifristul este un informatician care îºi cifreazã datele chiar ºi în cazurile cînd acest
lucru nu este necesar. Mai mult chiar, fiind distrat, el permanent uitã parolele, algoritmii
de descifrare, cheile cifrului º.a.m.d. Ultima lui invenþie reprezintã urmãtorul algoritm de
cifrare a mesajelor.
Mesajul iniþial reprezintã un ºir de caractere imprimabile ale codului ASCII, farã
spaþii, cu lungimea n. Pentru a cifra acest mesaj, cifristul foloseºte un ºablon în formã
de tabel cu m rînduri, m ≤ n, numãrul de coloane stabilindu-se în procesul cifrãrii (vezi
fig. 1). În fiecare celulã a tabelului poate fi înscris cîte un singur caracter. Iniþial toate
celulele tabelului conþin cîte un spaþiu.
1 P G M E
2 R R A
m=3 O A R
Fig. 1.
Mesajul iniþial se înscrie în tabel, cîte un caracter în fiecare celulã, de sus în jos, pe
coloane. Dupã completarea primei coloane, se trece la coloana a doua º.a.m.d., pînã
cînd tot mesajul va fi înscris în tabel. Pentru exemplificare, în tabelul din figurã este
înscris mesajul PROGRAMARE. Dupã completarea tabelului, se compune mesajul
cifrat, copiind în acest scop conþinutul tabelului, celulã dupã celulã, de la stînga la
dreapta, rîndurile tabelului fiind citite de sus în jos. De exemplu, în cazul tabelului din
fig. 1 mesajul cifrat este
PGMERRA OAR
23
Date de intrare.
Fiºierul text CIFRIST.IN constã din douã linii. Pe prima linie este înscris un ºir
de caractere - mesajul iniþial, iar pe a doua un alt ºir de caractere - mesajul cifrat.
Date de ieºire.
Fiºierul text CIFRIST.OUT va conþine pe o singurã linie cheia cifrului - numãrul
natural m.
Exemplu.
CIFRIST.IN CIFRIST.OUT
PROGRAMARE 3
PGMERRA OAR
Restricþii.
n ≤ 200. Timpul de execuþie nu va depãºi 2 secunde. Fiºierul sursã va avea
denumirea CIFRIST.PAS, CIFRIST.C sau CIFRIST.CPP.
24
Rezolvare
Program Cifristul;
var s,cifr:array[0..400] of char;
l,m,n:integer;
procedure Citire;
var f:text;
i:integer;
c:char;n1:integer;
begin
n1:=0;
assign(f,’cifrist.in’); reset(f);
while not eoln(f) do begin read(f,c);
inc(n1);s[n1]:=c; end;
readln(f);
l:=0;while not eoln(f) do
begin
read(f,c); inc(l);cifr[l]:=c;
end;
for i:=n1+1 to l do s[i]:=’ ’;
close(f);
end;
procedure Decodificare;
var i,j:integer; ok:boolean;
begin
m:=0;
repeat m:=m+1;
ok:=false;
if (l mod m)<>0 then continue;
ok:=true; n:=l div m;
for i:=1 to m do
begin
for j:=1 to n do
begin
if s[(j-1)*m+i]<>cifr[(i-1)*n+j] then
ok:=false;
if not(ok) then break;
end;
25
if not(ok) then break;
end;
if m>l then break;
until ok;
end;
procedure Afisare;
var i,j:integer;
f:text;
begin
assign(f,’Cifrist.out’); rewrite(f);
writeln(f,m);
close(f);
end;
begin
Citire;
Decodificare;
Afisare;
End.
26
Domino
Fig. 1 Fig. 2
Utilizînd n piese distincte de domino în calitate de vagoane imaginare, pe masa de
joc poate fi construit un “tren” cu proprietatea ca cele douã numere de pe pãrþile vecine
ale oricãror douã piese adiacente sînt egale între ele (figura 2). Lungimea trenului se
defineºte prin numãrul de piese m din componenþa lui. Evident, m ≤ n.
Date de intrare.
Fiºierul text DOMINO.IN conþine pe prima linie numãrul de piese n. Urmãtoarele
n linii ale fiºierului de intrare conþin cîte douã numere întregi separate prin spaþiu,
fiecare linie reprezentînd o piesã de domino.
Date de ieºire.
Fiºierul text DOMINO.OUT va conþine pe prima linie numãrul de piese m într-un
tren de lungime maximã. Urmãtoarele m linii ale fiºierului de ieºire vor conþine cîte
douã numere întregi separate prin spaþiu, fiecare linie reprezentînd o piesã de
domino. Piesele vor fi listate în ordinea apariþiei lor în tren, astfel încît cele douã
numere de pe pãrþile vecine ale oricãror douã piese adiacente sînt egale între ele.
27
Exemplu.
DOMINO.IN DOMINO.OUT
4 3
3 6 0 3
3 5 3 6
3 0 6 6
6 6
Restricþii.
1 ≤ n ≤ 10. Timpul de execuþie nu va depãºi 5 secunde. Fiºierul sursã va avea
denumirea DOMINO.PAS, DOMINO.C sau DOMINO.CPP.
28
Rezolvare
Pentru a calcula numãrul de piese din componenþa unui tren de lungime maximã,
vom examina consecutiv toate trenurile posibile ce pot fi construite din piesele date. În
acest scop vom simula pe calculator acþiunile jucãtorului în domino. Introducem în
studiu douã mulþimi ordonate:
C0 - mulþimea pieselor disponibile;
X - trenul în curs de construcþie.
Se observã cã mulþimea X poate fi construitã pas cu pas, alegînd din mulþimea
pieselor disponibile cîte una care satisface condiþiile problemei:
1) Iniþial includem în mulþimea X prima piesã din mulþimea C0: X := (x1). Evident,
aceastã piesã trebuie exclusã din mulþimea pieselor disponibile: C1 := C0 \ {x1}.
2) Alegem din mulþimea pieselor rãmase C1 prima piesã care satisface condiþiile
problemei ºi stabilim: X := (x1, x2); C2 := C1 \ {x2}.
3) Presupunem cã acest proces a ajuns la pasul k, în mulþimea X fiind deja incluse
k-1 piese:
X = (x1, x2, ..., xk-1).
Evident, algoritmul care simuleazã acþiunile jucãtorului poate fi realizat prin metoda
reluãrii, utilizînd în acest scop recursia.
În programul ce urmeazã, fiecare piesã de domino este reprezentatã cu ajutorul
tipului de date
Piesa = record
a, b : 0..6;
end;
29
iar mulþimile C ºi X - cu ajutorul structurilor
MultimePiese = record
k : integer;
p : array[1..28] of Piesa;
end;
Tren=MultimePiese;
Metoda reluãrii este realizatã în procedura cu acelaºi nume, iar trenul de lungime
maximã este memorat în variabila Xmax.
30
Program Domino; { Clasele 10-12 }
type Piesa=record
a, b : 0..6;
end;
MultimePiese=record
k : integer;
p : array[1..28] of Piesa;
end;
Tren=MultimePiese;
var n : integer;
C : MultimePiese;
X, Xmax : Tren;
31
close(Iesire);
end; { Scrie }
32
Corespunde:=false;
{ pozitia initiala a placii Q }
if X.p[X.k].b=Q.a then
begin
Corespunde:=true;
goto 1;
end;
if X.p[X.k].b=Q.b then
{ rotim placa Q }
begin
Corespunde:=true;
i:=Q.a;
Q.a:=Q.b;
Q.b:=i;
end;
1: end; { Corespunde }
33
procedure TrenMaxim(C : MultimePiese; X :Tren);
{ Cauta trenul de lungime maxima }
var i, j : integer;
Xmax : Tren;
begin
Xmax.k:=0;
X.k:=0;
Reluare(C, X);
{ rotim piesele cu care poate incepe trenul }
for i:=1 to C.k do
begin
j:=C.p[i].b; C.p[i].b:=C.p[i].a; C.p[i].a:=j;
end;
X.k:=0;
Reluare(C, X);
end; { Tren }
begin
Citeste(C, n);
TrenMaxim(C, X);
Scrie(Xmax);
end.
34
Ziua 2
Clasele 7-9
Descrierea problemelor
VOT.PAS
Votul 100 VOT.C VOT.IN VOT.OUT
VOT.CPP
METROU.PAS
Metroul 100 METROU.C METROU.IN METROU.OUT
METROU.CPP
ROBOTI.PAS
Roboţi 100 ROBOTI.C ROBOTI.IN ROBOTI.OUT
ROBOTI.CPP
Total 300 - - -
35
Votul
Date de intrare.
Fiºierul text VOT.IN constã din douã linii. Pe prima line este înscris numãrul
circumscripþiilor n. Linia a doua a fiºierului de intrare conþine n numere întregi
pozitive ce reprezintã numãrul alegãtorilor din fiecare circumscripþie.
Date de ieºire.
Fiºierul text VOT.OUT va conþine pe o singurã linie un numãr natural - numãrul
necesar de voturi.
36
Exemplu.
VOT.IN VOT.OUT
3 7
4 6 7
Restricþii.
n ≤ 1000. Numãrul de alegãtori pe insulã nu depãºeºte valoarea 30000.
Timpul de execuþie nu va depãºi 1 secundã. Fiºierul sursã va avea denumirea
VOT.PAS, VOT.C sau VOT.CPP.
37
Rezolvare
a1 ≤ a2 ≤ a3 ≤ ... ≤ an.
Program Votul;
{ Clasele 7-9 }
var A:array[1..1000] of integer;
n:integer;
vots:longint;
procedure InitData;
{ Citirea datelor de intrare }
var f:text; i:integer;
begin
assign(f,’vot.in’); reset(f);
readln(f,n);
for i:=1 to n do read(f,A[i]);
close(f);
end; { InitData }
procedure BubleSort;
{Sortarea vectorului A prin metoda bulelor }
var i,k,l,t:integer;
begin
l:=n-1;
38
while 1<=l do
begin
k:=0;
for i:=1 to l do
if A[i]>A[i+1] then
begin
t:=A[i]; A[i]:=A[i+1]; A[i+1]:=t;
k:=i;
end;
l:=k-1;
end;
end; { BubleSort }
procedure Calc;
{ Calcularea numarului minim de alegatori }
var i:integer;
begin
for i:=1 to (n div 2) +1 do
vots:=vots+((A[i] div 1)+1);
end; { Calc }
procedure Outputdata;
{ Extragerea datelor de iesire }
var f:text;
begin
assign(f,’vot.out’);
rewrite(f); writeln(f,vots);close(f);
end; { Outputdata }
begin
InitData;
BubleSort;
Calc;
OutputData;
end.
39
Metroul
Metroul din Londra reprezintã un sistem complex, care transportã zilnic milioane de
pasageri (fig. 1). Din punctul de vedere al pasagerului, metroul poate fi tratat ca o
mulþime de linii de tren ºi o mulþime de staþii. În scopuri didactice, vom nota liniile de tren
prin literele mari A, B, C, D º.a.m.d. ale alfabetului latin, în total n linii, iar staþiile - prin
numerele naturale 1, 2, 3, ..., în total m staþii (fig. 2).
Fig. 1 Fig. 2
Liniile de tren ºi staþiile respective au fost proiectate în aºa fel, încît pasagerul, care
pleacã din orice staþie x, sã poatã ajunge în oricare altã staþie y. Evident, în cazurile în
care staþiile se aflã pe linii diferite, pasagerul este nevoit sã facã una sau mai multe
transbordãri, schimbînd trenul în staþiile în care se întîlnesc douã sau mai multe linii de
tren. De exemplu, pentru a ajunge din staþia 1 în staþia 8 (fig. 2), pasagerul poate sã
facã o singurã transbordare în staþia 2 sau douã transbordãri - prima în staþia 4 ºi a
doua în staþia 6.
În caz de reparaþii, unele staþii de metrou pot fi temporar închise pentru transbordarea
pasagerilor. În astfel de cazuri, nu întotdeauna pasagerul care pleacã din staþia x, poate
sã ajunge în oricare altã staþie y. De exemplu, dacã staþia 5 va fi închisã pentru
transbordãri (fig. 2), pasagerii care pleacã din staþia 1 nu mai pot ajunge în staþia 9. Un
alt exemplu poate servi închiderea staþiei 2, care însã, nu împiedicã pasagerii ce pleacã
din staþia 1 sã ajungã în oricare altã staþie de metrou.
40
Date de intrare.
Fiºierul text METROU.IN conþine pe prima linie numerele naturale n, m, x,
y, z separate prin spaþiu. Fiecare din urmãtoarele n linii ale fiºierului conþine
numere de staþii separate prin spaþiu. Linia a 2-a a fiºierului de intrare conþine
numerele de staþii ale liniei de tren A, linia a treia a fiºierului de intrare conþine
numerele de staþii ale liniei de tren B º.a.m.d.
Date de ieºire.
Fiºierul text METROU.OUT va conþine pe o singurã linie cuvîntul DA dacã pasagerul
poate ajunge din staþia x în staþia y ºi NU în caz contrar.
Exemplu.
METROU.IN METROU.OUT
4 9 1 8 2 DA
1 2 3 4 5
2 6 8
7 6 4
5 9
Restricþii.
2 ≤ n ≤ 26, 3 ≤ m ≤ 250, x ≠ y, x ≠ z, y ≠ z. Timpul
de execuþie nu va depãºi 5 secunde. Fiºierul sursã va avea denumirea
METROU.PAS, METROU.C sau METROU.CPP.
41
Rezolvare
Introducem în studiu mulþimile L1, L2, ..., Ln, fiecare mulþime reprezentînd cîte o linie
de tren. De exemplu, în cazul fig. 2, avem:
L1 = {1, 2, 3, 4, 5} - linia A;
L2 = { 2, 6, 8} - linia B;
L3 = {7, 6, 4} - linia C;
L4 = { 5, 9} - linia D.
Fie S mulþimea staþiilor de metrou la care se poate ajunge pornind din staþia x.
Aceastã mulþime poate fi calculatã iterativ dupã cum urmeazã:
1) Iniþial includem în mulþimea S0 toate staþiile de pe liniile pe care apare staþia x.
2) Presupunem cã la un anumit pas k avem deja calculatã mulþimea Sk-1. Mulþimea
Sk se obþine adãugînd la mulþimea Sk-1 toate staþiile de pe liniile pe care apare cel
puþin o staþie din mulþimea Sk-1. Evident, S0 ⊆ S1 ⊆ S2 ⊆ ...⊆ Sk, iar în
mulþimile S0, S1, S2, ..., Sk nu trebuie sã aparã staþia z, care este închisã pentru
transbordãri.
3) Indiferent de configuraþia liniilor de metrou, numãrul necesar de transbordãri
nu poate depãºi valoarea n-1. Prin urmare, mulþimile Sk trebuie calculate pentru
k = 1, 2, 3 º.a.m.d, în cel mai nefavorabil caz, pînã la k = n-1.
Pe calculator mulþimile S0, S1, S2, ..., Sk pot fi reprezentate cu ajutorul unui singur
42
Program Metro;
{ Clasele 7-9 }
const nmax=26;
mmax=250;
type Linie = set of 1..mmax;
var L : array [1..26] of Linie;
n : 2..nmax;
m, x, y, z : 3..mmax;
T : array[1..mmax] of boolean;
procedure Citeste;
{ Citirea datelor de intrare }
var i, j : integer;
Intrare : text;
begin
assign(Intrare, ’METRO.IN’);
reset(Intrare);
readln(Intrare, n, m, x, y, z);
for i:=1 to n do
begin
L[i]:=[];
while not eoln(Intrare) do
begin
read(Intrare, j);
L[i]:=L[i]+[j];
end; { while }
readln(Intrare);
end; { for }
close(Intrare);
end; { Citeste }
procedure Scrie;
{ Scrierea datelor in fisierul de iesire }
var i, j, k : integer;
Iesire : text;
begin
assign(Iesire, ’METRO.OUT’);
rewrite(Iesire);
43
if T[y] then writeln(Iesire, ’DA’)
else Writeln(Iesire, ’NU’);
close(Iesire);
end; { Scrie }
procedure Accesibilitate;
{ Calculeaza vectorul T }
var i, j, k, q : integer;
begin
{excludem statia z din toate liniile de metrou}
for i:=1 to n do
if (z in L[i]) then L[i]:=L[i]-[z];
{ initializam vectorul T }
for j:=1 to m do T[j]:=false;
{ calculam multimea S0 }
for i:=1 to n do
if (x in L[i]) then
for j:=1 to m do
if (j in L[i]) then T[j]:=true;
{ calculam multimile Sk }
for k:=1 to n-1 do
for i:=1 to n do
for j:=1 to m do
if ((j in L[i]) and T[j]) then
for q:=1 to m do
if (q in L[i]) then T[q]:=true;
end; { Accesibilitate }
begin
Citeste;
Accesibilitate;
Scrie;
end.
Date de intrare.
Fiºierul text ROBOTI.IN conþine pe o singurã linie numerele naturale k0 ºi n
separate prin spaþiu.
Date de ieºire.
Fiºierul text ROBOTI.OUT va conþine pe o singurã linie numãrul natural kn.
Exemplu.
ROBOTI.IN ROBOTI.OUT
8 2 60
Restricþii.
7 < k0 ≤ 25, 1 ≤ n ≤ 19. Timpul de execuþie nu va depãºi 1 secundã. Fiºierul sursã
va avea denumirea ROBOTI.PAS, ROBOTI.C sau ROBOTI.CPP.
45
Rezolvare
s = r 1 + r2 + r3 .
Vom nota x numãrul maxim de grupe de cîte 3 indivizi ce pot fi formate din populaþia
cu s roboþi, iar prin y - numãrul grupelor formate din cîte 5 roboþi. Notînd prin p restul
împãrþirii numãrului de roboþi s la 3 sau, prin alte notaþii, p = s mod 3, se observã cã
numerele x ºi y pot fi determinate ca:
Cunoscînd numãrul curent de roboþi ºi divizarea lor în grupe, putem simula procesele
de “naºtere” ºi “îmbãtrînire” a roboþilor:
r3 := r2;
r2 := r1;
r1 := 5x + 9y.
46
Program Roboti;
{ Clasele 7-9 }
var f:text;
i,N,k:integer;
r:array[1..3] of longint;
s:longint;
x,y,p:longint;
begin
assign(f,’roboti.in’); reset(f);
readln(f,k,N); close(f);
r[1]:=k; r[2]:=0; r[3]:=0; s:=k;
for i:=1 to n do
begin
x:=s div 3; p:=s mod 3;
if p=0 then y:=0;
if p=2 then begin x:=x-1; y:=1; end;
if p=1 then begin x:=x-3; y:=2; end;
r[3]:=r[2]; r[2]:=r[1]; r[1]:=5*x+9*y;
s:=r[1]+r[2]+r[3];
end;
assign(f,’roboti.out’); rewrite(f); writeln(f,s);
close(f);
end.
47
Ziua 2
Clasele 10 - 12
Descrierea problemelor
VOT.PAS
Votul 100 VOT.C VOT.IN VOT.OUT
VOT.CPP
METROU.PAS
Metroul 100 METROU.C METROU.IN METROU.OUT
METROU.CPP
CINA.PAS
Cina 100 CINA.C CINA.IN CINA.OUT
CINA.CPP
Total 300 - - -
48
Votul
Date de intrare.
Fiºierul text VOT.IN constã din douã linii. Pe prima line este înscris numãrul
circumscripþiilor n. Linia a doua a fiºierului de intrare conþine n numere întregi
pozitive ce reprezintã numãrul alegãtorilor din fiecare circumscripþie.
Date de ieºire.
Fiºierul text VOT.OUT va conþine pe o singurã linie un numãr natural - numãrul
necesar de voturi.
49
Exemplu.
VOT.IN VOT.OUT
3 7
4 6 7
Restricþii.
n ≤ 1000. Numãrul de alegãtori pe insulã nu depãºeºte valoarea 30000.
Timpul de execuþie nu va depãºi 1 secundã. Fiºierul sursã va avea denumirea
VOT.PAS, VOT.C sau VOT.CPP.
50
Rezolvare
a1 ≤ a2 ≤ a3 ≤ ... ≤ an.
Program Votul;
{ Clasele 7-9 }
var A:array[1..1000] of integer;
n:integer;
vots:longint;
procedure InitData;
{ Citirea datelor de intrare }
var f:text; i:integer;
begin
assign(f,’vot.in’); reset(f);
readln(f,n);
for i:=1 to n do read(f,A[i]);
close(f);
end; { InitData }
procedure BubleSort;
{Sortarea vectorului A prin metoda bulelor }
var i,k,l,t:integer;
begin
l:=n-1;
51
while 1<=l do
begin
k:=0;
for i:=1 to l do
if A[i]>A[i+1] then
begin
t:=A[i]; A[i]:=A[i+1]; A[i+1]:=t;
k:=i;
end;
l:=k-1;
end;
end; { BubleSort }
procedure Calc;
{ Calcularea numarului minim de alegatori }
var i:integer;
begin
for i:=1 to (n div 2) +1 do
vots:=vots+((A[i] div 1)+1);
end; { Calc }
procedure Outputdata;
{ Extragerea datelor de iesire }
var f:text;
begin
assign(f,’vot.out’);
rewrite(f); writeln(f,vots);close(f);
end; { Outputdata }
begin
InitData;
BubleSort;
Calc;
OutputData;
end.
52
Metroul
Metroul din Londra reprezintã un sistem complex, care transportã zilnic milioane de
pasageri (fig. 1). Din punctul de vedere al pasagerului, metroul poate fi tratat ca o
mulþime de linii de tren ºi o mulþime de staþii. În scopuri didactice, vom nota liniile de tren
prin literele mari A, B, C, D º.a.m.d. ale alfabetului latin, în total n linii, iar staþiile - prin
numerele naturale 1, 2, 3, ..., în total m staþii (fig. 2).
Fig. 1 Fig. 2
Liniile de tren ºi staþiile respective au fost proiectate în aºa fel, încît pasagerul, care
pleacã din orice staþie x, sã poatã ajunge în oricare altã staþie y. Evident, în cazurile în
care staþiile se aflã pe linii diferite, pasagerul este nevoit sã facã una sau mai multe
transbordãri, schimbînd trenul în staþiile în care se întîlnesc douã sau mai multe linii de
tren.
De exemplu, pentru a ajunge din staþia 1 în staþia 8 (fig. 2), pasagerul poate sã facã
o singurã transbordare în staþia 2 sau douã transbordãri - prima în staþia 4 ºi a doua în
staþia 6.
Date de intrare.
Fiºierul text METROU.IN conþine pe prima linie numerele naturale n, m, x,
y separate prin spaþiu. Fiecare din urmãtoarele n linii ale fiºierului conþine numere
de staþii separate prin spaþiu. Linia a 2-a a fiºierului de intrare conþine numerele de
staþii ale liniei de tren A, linia a treia a fiºierului de intrare conþine numerele de staþii
ale liniei de tren B º.a.m.d.
53
Date de ieºire.
Fiºierul text METROU.OUT va conþine pe o singurã linie numãrul minim de
transbordãri.
Exemplu.
METROU.IN METROU.OUT
4 9 1 8 1
1 2 3 4 5
2 6 8
7 6 4
5 9
Restricþii.
2 ≤ n ≤ 26, 3 ≤ m ≤ 250, x ≠ y. Timpul de execuþie nu va depãºi
5 secunde. Fiºierul sursã va avea denumirea METROU.PAS, METROU.C sau
METROU.CPP.
54
Rezolvare
Introducem în studiu mulþimile L1, L2, ..., Ln, fiecare mulþime reprezentînd cîte o linie
de tren. De exemplu, în cazul fig. 2, avem:
L1 = {1, 2, 3, 4, 5} - linia A;
L2 = { 2, 6, 8} - linia B;
L3 = {7, 6, 4} - linia C;
L4 = { 5, 9} - linia D.
Mulþimile S0, S1, S2, ..., Sk pot fi calculate iterativ, dupã cum urmeazã:
Pe calculator mulþimile S0, S1, S2, ..., Sk pot fi reprezentate cu ajutorul unui singur
55
În programul ce urmeazã liniile de tren ºi vectorul transbordãrilor sînt reprezentate
prin structurile de date
const nmax=26;
mmax=250;
type Linie = set of 1..mmax;
var L : array [1..26] of Linie;
n : 2..nmax;
m, x, y : 3..mmax;
T : array[1..mmax] of integer;
iar apartenenþa staþiilor la anumite linii de metrou se verificã cu ajutorul operatorului in.
Program Metro;
{ Clasele 10-12 }
const nmax=26;
mmax=250;
type Linie = set of 1..mmax;
var L : array [1..26] of Linie;
n : 2..nmax;
m, x, y : 3..mmax;
T : array[1..mmax] of integer;
procedure Citeste;
{ Citirea datelor de intrare }
var i, j : integer;
Intrare : text;
begin
assign(Intrare, ’METRO.IN’);
reset(Intrare);
readln(Intrare, n, m, x, y);
for i:=1 to n do
begin
L[i]:=[];
while not eoln(Intrare) do
begin
read(Intrare, j);
56
L[i]:=L[i]+[j];
end; { while }
readln(Intrare);
end; { for }
close(Intrare);
end; { Citeste }
procedure Scrie;
{ Scrierea datelor in fisierul de iesire }
var i, j, k : integer;
Iesire : text;
begin
assign(Iesire, ’METRO.OUT’);
rewrite(Iesire);
writeln(Iesire, T[y]);
close(Iesire);
end; { Scrie }
procedure Transbordari;
{ Calculeaza vectorul T }
var i, j, k, q : integer;
begin
{ initializam vectorul T }
for j:=1 to m do T[j]:=-1;
{ calculam multimea S0 }
for i:=1 to n do
if (x in L[i]) then
for j:=1 to m do
if (j in L[i]) then T[j]:=0;
{ calculam multimile Sk }
for k:=1 to n-1 do
for i:=1 to n do
for j:=1 to m do
if ((j in L[i]) and (T[j]=k-1)) then
for q:=1 to m do
if ((q in L[i]) and (T[q]=-1)) then
T[q]:=k;
end; { Transbordari }
57
begin
Citeste;
Transbordari;
Scrie;
end.
58
Cina
Pentru organizarea unei cine festive ar fi necesare d1 pîini de calitatea 1-a, d2 pîini
de calitatea a 2-a, d3 pîini de calitatea a 3-a, ..., dn pîini de calitatea n. Preþurile la pîine
diferã, astfel o pîine de calitatea 1-a costã c1 lei, o pîine de calitatea a 2-a costã c2 lei, ...,
o pîine de calitatea n costã cn lei. Se considerã, cã pîinea de calitatea 1-a este bunã, de
calitatea a 2-a - mai bunã, ..., iar de calitatea n - cea mai bunã. Evident, concomitent cu
îmbunãtãþirea calitãþii, cresc ºi preþurile respective, ºi anume, c1 < c2 < c3 < ... < cn. În
general, organizatorii cinei festive sînt de acord sã înlocuiascã pîinile de calitate bunã
prin acelaºi numãr de pîini de calitate ºi mai bunã, însã ar dori sã plãteascã cît mai puþini
bani.
De exemplu, presupunem cã
d1 = 6, d2 = 1, d3 = 0, d4 = 6,
în total 13 pîini, ºi
c1 = 1, c2 = 4, c3 = 7, c4 = 8.
Dacã s-ar cumpãra asortimentul indicat, pentru pîini s-ar plãti 123 de lei. Dacã însã,
reducem asortimentul ºi cumpãrãm
d1 = 6, d2 = 0, d3 = 0, d4 = 7,
59
Date de intrare.
Fiºierul text CINA.IN conþine pe prima linie numãrul natural n. Fiecare din
urmãtoarele n linii ale fiºierului de intrare conþine cîte douã numere naturale separate
prin spaþiu. Pe linia i +1 sînt înscrise numerele ci, di, separate prin spaþiu.
Date de ieºire.
Fiºierul text CINA.OUT va conþine pe o singurã linie un numãrul natural - suma
minimã de bani necesarã pentru procurarea pîinii.
Exemplu.
CINA.IN CINA.OUT
4 107
1 6
4 1
7 0
8 6
Restricþii.
1 ≤ n ≤ 1000, 1 ≤ ci ≤ 10000, 0 ≤ di ≤ 100. Timpul de
execuþie nu va depãºi 1 secundã. Fiºierul sursã va avea denumirea CINA.PAS,
CINA.C sau CINA.CPP.
60
Rezolvare
R1 = c1(d1+5).
61
Program Cina;
{ Clasele 10-12 }
var
C : array[0..1000] of integer;
D : array[0..1000] of integer;
R : array[0..1000] of longint;
{ suma minima pentru a satisface cererea
organizatorilor in calitatile 1..i}
S : array[0..1000] of longint;
{numarul piinilor care vor cerute de calitatea
1..i}
n: integer;
t: integer;
{indicele celei mai mari calitatii solicitate de
organizatori}
procedure CitesteDate;
{citeste datele din fisierul de intrare}
var f:text;
i:integer;
begin
assign(f,’Piini.in’); reset(f);
readln(f,n);
for i:=1 to n do readln(f,C[i],D[i]);
close(f);
end; { CitesteDate }
procedure Process;
var i,j,p:integer;
begin
R[0]:=0;
for i:=1 to n do if D[i]>0 then t:=i;
{t va reprezenta calitatea cea mai mare pentru
care organizatorii au solicitat piine }
s[0]:=0;
for i:=1 to n do s[i]:=s[i-1]+D[i];
for i:=1 to n do
begin
R[i]:=R[i-1]+(D[i]+5)*C[i];
for j:=i-1 downto 1 do
62
begin
if R[i]>R[j-1]+(s[i]-s[j-1]+5)*C[i]
then
R[i]:=R[j-1]+(s[i]-s[j-1]+5)*C[i];
{ incearca sa micsorezi pretul }
end; { for j }
end; { for i }
end; { Process }
procedure ScrieDate;
{Scrie datele in fisierul de iesire }
var f:text; i:integer;
begin
assign(f,’piini.out’); rewrite(f);
writeln(f,R[t]);
close(f);
end; { ScrieDate }
begin
CitesteDate;
Process;
ScrieDate;
end.
63
64