Documente Academic
Documente Profesional
Documente Cultură
◦ Recursivitatea
◦ Metoda Backtracking
◦ Metoda Divide et impera
◦ Metoda Greedy
◦ Metoda Branch and Bound
◦ Metode euristice
◦ Metoda programării liniare
◦ Metoda programării dinamice
Una dintre metodele de rezolvare a problemelor
Este o strategie de cautare sistematica in spatiul solutiilor unei probleme
Observații
Uneori n nu e cunoscut de la început
x1, x2,…xk,… xn pot fi vectori la rândul lor
Mulțimile A1 x A2 x… x An pot coincide
Ideea de baza:
Principiul tehnicii poate fi vizualizat folosind arbore de cautare care ilustreaza
parcurgerea spatiului solutiilor:
◦ Radacina arborelui corespunde starii initiale (inainte de a incepe completarea
componentelor)
◦ Un nod intern corespunde unei solutii partiale valide
◦ Un nod extern (frunza) corespunde fie unei solutii partiale invalide fie unei solutii
finale
Exemplu: arborele de parcurgere a spatiului solutiilor in cazul problemei de generare a
permutarilor (n=3)
(3,3,*)
(1,2,*) (1,3,*) (2,1,*) (2,2,*) (2,3,*) (3,1,*) (3,2,*)
Convenții:
La urcarea în stivă, se pune o valoare care nu află în mulțimea considerată,
dar, de la care, la pasul următor, se ajunge la primul element din acea
mulțime (procedura INIT)
Pe un anumit nivel găsirea elementului următor celui considerat se face
folosind procedura SUCCESOR
Verificarea faptului că sunt îndeplinite condițiile de continuare a algoritmului
se face folosind procedura VALID
Testarea dacă s-a ajuns la o soluție se face folosind funcția SOLUȚIE
Tipărirea soluției se face folosind procedura TIPAR
as, ev variabile booleene (am succesor, e valid)
Procedurile și funcția else write(' - ');
procedure init(k:integer;var st:stiva); writeln;
Begin end;
st[k]:=0; End;
End;
procedure succesor(var as:boolean;var st:stiva;k:integer); Partea fixă a algoritmului
begin k:=1;
if st[k]<n then
begin
init(k,st);
st[k]:=st[k]+1; while k>0 do
as:=true;
begin
end
else as:=false repeat
End; succesor(asss,st,k);
procedure valid(var ev:boolean;st:stiva;k:integer);
var i:integer; if as then valid(ev,st,k)
begin until (not as) or (as and ev);
ev:=true;
for i:=1 to k-1 do if as then
if (st[i]=st[k]) or (abs(st[i]-st[k])=abs(i-k)) then ev:=false; if solutie(k) then tipar
End;
function solutie(k:integer):boolean;
else
begin begin
solutie:=(k=n);
k:=k+1;
End;
procedure tipar; init(k,st)
var i:integer; end
begin
l:=l+1; writeln('Solutia ',l); else k:=k-1;
for i:=1 to n do end;
begin
for j:=1 to n do readkey;
if j=st[i] then write(' D ') End.
Fiind data o tabla de sah de dimensiune nxn, se cer toate solutiile de aranjare a n
dame astfel incat doua dame sa nu se afle pe acceasi linie, coloana sau diagonala
(damele sa nu se atace reciproc).
Conditii de continuare:
Fie (x1,x2,…,xk) o solutie partiala. Aceasta este valida daca satisface:
Reginele se afla pe linii diferite - conditia este implicit satisfacuta datorita modului de
reprezentare utilizat (regina i este intotdeauna plasata pe linia i)
Reginele se afla pe coloane diferite: xi<>xk pentru orice i<>k
(este suficient sa se verifice ca xk<>xi pentru orice 1<= i <=k-1)
Reginele se afla pe diagonale diferite: |i-k| <> |xi – xk| pentru orice i<>k
(este suficient sa se verifice |k-i|<>| xk - xi| pentru orice 1<= i <=k-1)
program dame; procedure tipar;
type stiva=array [1..100] of integer; var i:integer;
begin
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean;
l:=l+1; writeln('Solutia ',l);
procedure init(k:integer;var st:stiva); for i:=1 to n do
begin begin
st[k]:=0; for j:=1 to n do
if j=st[i] then write(' D ')
end;
else write(' - ');
procedure succesor(var as:boolean;var st:stiva;k:integer); writeln;
begin end;
if st[k]<n then end;
begin begin
l:=0;
st[k]:=st[k]+1;
write('n='); read(n);
as:=true; k:=1;
end init(k,st);
else as:=false while k>0 do
end; begin
repeat
procedure valid(var ev:boolean;st:stiva;k:integer); succesor(as,st,k);
var i:integer; if as then valid(ev,st,k)
begin until (not as) or (as and ev);
ev:=true; if as then
if solutie(k) then tipar
for i:=1 to k-1 do
else
if (st[i]=st[k]) or (abs(st[i]-st[k])=abs(i-k)) then ev:=false; begin
end; k:=k+1;
function solutie(k:integer):boolean; init(k,st)
end
begin
else k:=k-1;
solutie:=(k=n); end;
end; end.
Se citeste un numar natural n. Sa se genereze toate permutarile multimii
{1,2,...n}.
Observații:
Stiva are înălțimea n
Fiecare nivel ia valori între 1 și n
Elementele plasate pe diverse niveluri trebuie să fie distincte
Exemplu:
N=3
123
132
213
231
312
321
program permutari; procedure tipar;
type stiva=array [1..100] of integer; var i:integer;
begin
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean;
l:=l+1; writeln('Solutia ',l);
procedure init(k:integer;var st:stiva); for i:=1 to n do
begin write(st[i], ‘ ‘);
st[k]:=0; writeln;
end;
end;
end;
procedure succesor(var as:boolean;var st:stiva;k:integer); begin
begin l:=0;
if st[k]<n then write('n='); read(n);
begin k:=1;
init(k,st);
st[k]:=st[k]+1;
while k>0 do
as:=true; begin
end repeat
else as:=false succesor(as,st,k);
end; if as then valid(ev,st,k)
until (not as) or (as and ev);
procedure valid(var ev:boolean;st:stiva;k:integer); if as then
var i:integer; if solutie(k) then tipar
begin else
ev:=true; begin
k:=k+1;
for i:=1 to k-1 do
init(k,st)
if (st[i]=st[k]) then ev:=false; end
end; else k:=k-1;
function solutie(k:integer):boolean; end;
end.
begin
solutie:=(k=n);
end;
Se citesc n si p numere naturale. Sa se genereze toate submultimile cu p
elemente ale multimii {1,2,...n}. Doua multimi cu aceleasi elemente, la care
difera ordinea sunt considerate distincte.
Observații:
Stiva are înălțimea p
Fiecare nivel ia valori între 1 și n
Elementele plasate pe diverse niveluri trebuie să fie distincte
Exemplu:
N=3
P=2
12
13
21
23
31
32
program aranjamente; procedure tipar;
type stiva=array [1..100] of integer; var i:integer;
begin
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean;
l:=l+1; writeln('Solutia ',l);
procedure init(k:integer;var st:stiva); for i:=1 to p do
begin write(st[i], ‘ ‘);
st[k]:=0; writeln;
end;
end;
end;
procedure succesor(var as:boolean;var st:stiva;k:integer); begin
begin l:=0;
if st[k]<n then write('n='); read(n);
begin write(‘p='); read(p);
k:=1;
st[k]:=st[k]+1;
init(k,st);
as:=true; while k>0 do
end begin
else as:=false repeat
end; succesor(as,st,k);
if as then valid(ev,st,k)
procedure valid(var ev:boolean;st:stiva;k:integer); until (not as) or (as and ev);
var i:integer; if as then
begin if solutie(k) then tipar
ev:=true; else
begin
for i:=1 to k-1 do
k:=k+1;
if (st[i]=st[k]) then ev:=false; init(k,st)
end; end
function solutie(k:integer):boolean; else k:=k-1;
end;
begin
end.
solutie:=(k=p);
end;
Se citesc n si p numere naturale (n>=p). Sa se genereze toate submultimile cu
p elemente ale multimii {1,2,...n}. Doua multimi se considera egale daca si
numai daca au aceleasi elemente, indiferent de ordinea in care acestea apar.
Observații:
Stiva are înălțimea p
Fiecare nivel ia valori între 1 și n-p+k
Elementele plasate pe diverse niveluri trebuie să fie distincte
Este necesar ca pe nivelul k să se afle o valoare mai mare decât pe nivelul k-1
(st[k-1]<st[k])
Exemplu:
N=3
P=2
12
13
23
program combinari; procedure tipar;
type stiva=array [1..100] of integer; var i:integer;
begin
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean;
l:=l+1; writeln('Solutia ',l);
procedure init(k:integer;var st:stiva); for i:=1 to p do
begin write(st[i], ‘ ‘);
st[k]:=0; writeln;
end;
end;
end;
procedure succesor(var as:boolean;var st:stiva;k:integer); begin
begin l:=0;
if st[k]<n-p+k then write('n='); read(n);
begin write(‘p='); read(p);
k:=1;
st[k]:=st[k]+1;
init(k,st);
as:=true; while k>0 do
end begin
else as:=false repeat
end; succesor(as,st,k);
if as then valid(ev,st,k)
procedure valid(var ev:boolean;st:stiva;k:integer); until (not as) or (as and ev);
var i:integer; if as then
begin if solutie(k) then tipar
ev:=true; else
begin
for i:=1 to k-1 do
k:=k+1;
if (st[i]=st[k]) then ev:=false; init(k,st)
if st[k]<st[k-1] then ev:=false; end
end; else k:=k-1;
end;
function solutie(k:integer):boolean;
end.
begin solutie:=(k=p);
end;
Se dau multimile
A1={1,2,...k1} A2={1,2,...k2} ... An={1,2,...kn}
Se cere produsul cartezian A1xA2x...xAn={(x1,x2,...xn) | x1 apartine A1, x2
apartine A2,... xn apartine An}
Exemplu
A1={1,2} A2={1,2,3} A3={1,2,3}
A1xA2xA3={(1,1,1),(1,1,2),(1,1,3)
(1,2,1),(1,2,2),(1,2,3)
(1,3,1),(1,3,2),(1,3,3)
(2,1,1),(2,1,2),(2,1,3)
(2,2,1),(2,2,2),(2,2,3)
(2,3,1),(2,3,2),(2,3,3) }
Vectorul a=k1,k2,…kn.
Orice element de pe nivelul k este valid
Limita superioară pe nivelul k al stivei este dată de a[k]
Algoritmul se tremină când nu mai avem succesor pe nivelul 1
program prod_cartez; procedure tipar;
type stiva=array [1..100] of integer; var i:integer;
begin
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean;
l:=l+1; writeln('Solutia ',l);
a:array[1..100] of integer; for i:=1 to n do
procedure init(k:integer;var st:stiva); write(st[i], ‘ ‘);
begin writeln;
end;
st[k]:=0;
end;
end; begin
procedure succesor(var as:boolean;var st:stiva;k:integer); l:=0;
begin write('n='); read(n); for i:=1 to n do read(a[i]);
k:=1;
if st[k]<a[k] then
init(k,st);
begin while k>0 do
st[k]:=st[k]+1; begin
as:=true; repeat
end succesor(as,st,k);
if as then valid(ev,st,k)
else as:=false
until (not as) or (as and ev);
end; if as then
procedure valid(var ev:boolean;st:stiva;k:integer); if solutie(k) then tipar
var i:integer; else
begin begin
k:=k+1;
ev:=true; init(k,st)
end; end
function solutie(k:integer):boolean; else k:=k-1;
begin end;
end.
solutie:=(k=n);
end;
Se considera multimea {1,2,...n}. Se cer toate partitiile acestei multimi.
Submultimile A1,A2,...Ak ale unei multimi A constituie o partitie a acesteia daca
acestea sunt disjuncte intre ele (nu au elemente comune) si multimea rezultata
in urma reuniunii lor este A.
Exemplu:
N=2
S=5
A[1]=1 B[1]=5
A[2]=3 B[2]=1
Solutie: 5=5*1+0*3 st=[5 0]
Solutie: 5=2*1+1*3 st=[2 1]
Se va calcula in vectorul b numarul maxim de monede de tipul I cu care se poate
plati suma s: b[i]=s/a[i]
Aceestea reprezinta limitele de cautare a succesorului pentru fiecare nivel al
stivei st
Prima valoare valida pe fiecare nivel al stivei este 0
Pentru a avea un succesor este nevoie ca:
◦ Succesorul sa fie <= valoarea corespunzatoare din vectorul b
◦ Suma calculata utilizand numarul de monede de tipul i gasite pe nivelul i al
stivei s1 trebuie sa fie <= s
program plata_suma; for i:=1 to n do
type stiva=array [1..100] of integer; s1:=s1+st[i]*a[i];
solutie:=(s=s1);
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean;
end;
a,b:array[1..100] of integer; procedure tipar;
procedure init(k:integer;var st:stiva); var i:integer;
begin begin
l:=l+1; writeln('Solutia ',l);
st[k]:=-1;
for i:=1 to n do
end; write(st[i], ‘ de ‘,a[i], ‘ lei’);
procedure succesor(var as:boolean;var st:stiva;k:integer); writeln;
begin end;
end;
if (st[k]<b[k]) and (k<=n) then
begin
begin l:=0; writeln(‘Cate tipuri de monede sunt’);
s1:=0; write('n='); read(n); writeln(‘Suma’);
for i:=1 to k do write(‘s='); read(s); writeln(‘Valorile monedelor’);
s1:=s1+st[i]*a[i]; for i:=1 to n do begin read(a[i]); b[i]:=s div a[i];end;
k:=1;
as:=(s1<s);
init(k,st);
end while k>0 do
else as:=false; begin
if as then st[k]:=st[k]+1; repeat
end; succesor(as,st,k);
if as then valid(ev,st,k)
procedure valid(var ev:boolean;st:stiva;k:integer); until (not as) or (as and ev);
var i:integer; if as then
begin if solutie(k) then tipar
ev:=true; else
begin
end;
k:=k+1;
function solutie(k:integer):boolean; init(k,st)
begin end
s1:=0; else k:=k-1; end; end.
Un comis voiajor trebuie sa viziteze un numar de n orase. Initial, acesta se afla
intr-unul dintre ele, notat 1. Comis voiajorul doreste sa nu treaca de doua ori
prin acelasi oras, iar la intoarcere sa revina in orasul 1. Cunoscand legaturile
existente intre orase, se cere sa se tipareasca toate drumurile posibile pe care
le poate efectua comis voiajorul.
Exemplu:
Orase:
1.Arad
2.Brasov
3.Bucuresti
4.Constanta
5.Iasi
6.Satu-Mare Satu Mare
Iasi
7.Timisoara
Brasov
Trasee de la Arad la Constanta: Arad