Sunteți pe pagina 1din 32

 Cele mai utilizate tehnici de programare structurată sunt :

◦ 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

 Se utilizeaza in special pentru rezolvarea problemelor a caror cerinta este de a


determina configuratii care satisfac anumite restrictii (probleme de satisfacere a
restrictiilor). Majoritatea problemelor ce pot fi rezolvate folosind tehnica cautarii cu
revenire se incadreaza in urmatorul sablon:
 “Sa se gaseasca o submultime S a produsului cartezian A1 x A2 x … x An (Ak –
multimi finite) avand proprietatea ca fiecare element s=(s1,s2,…,sn) satisface anumite
restrictii”
Exemplu: generarea tuturor permutarilor multimii {1,2,…,n}
Ak = {1,2,…,n} pentru fiecare k=1..n
si <> sj pentru orice i<>j (restrictia: componente distincte)
 Metoda reduce timpul de execuție
 Crește complexitatea (va fi exponențială)
 Se aplică problemelor în care soluţia poate fi reprezentată sub forma unui vector –
x = (x1, x2, x3, …xk,… xn) € A, unde A este mulţimea soluţiilor problemei şi A =
A1 x A2 x… x An, şi Ai sunt mulţimi finite având xi € Ai , (¥)i = 1..n.
 Problemele rezolvate prin această metodă necesită timp mare de execuţie, de
aceea este indicat sa se folosească metoda numai daca nu avem alt algoritm
de rezolvare.
 Pentru fiecare problemă se dau relaţii între componentele vectorului x, care sunt
numite condiţii interne; soluţiile posibile care satisfac condiţiile interne se numesc
soluţii rezultat. Metoda de generare a tuturor soluţiilor posibile si apoi de
determinare a soluţiilor rezultat prin verificarea îndeplinirii condiţiilor interne
necesită foarte mult timp.
 Metoda backtracking evită această generare şi este mai eficientă. Elementele
vectorului x, primesc pe rând valori în ordinea crescătoare a indicilor, x[k] va
primi o valoare numai daca au fost atribuite valori elementelor x1.. x[k-1]. La
atribuirea valorii lui x[k] se verifica îndeplinirea unor condiţii de continuare
referitoare la x1…x[k-1]. Daca aceste condiţii nu sunt îndeplinite, la pasul k,
acest lucru înseamnă ca orice valori i-am atribui lui x[k+1], x[k+1], .. x[n] nu se
va ajunge la o soluţie rezultat.
 Metoda backtracking construieşte un vector soluţie în mod progresiv începând cu
prima componentă a vectorului şi mergând spre ultima cu eventuale reveniri
asupra atribuirilor anterioare.

 Condiții de aplicare a metodei Backtracking
 Soluția problemei se poate reprezenta sub forma unui vector x=(x1, x2,… xn)
 Mulțimile A1, A2,…An sunt finite și ordonate iar între elementele lor există o
relație de ordine bine stabilită

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

(1,*,*) (2,*,*) (3,*,*)

(3,3,*)
(1,2,*) (1,3,*) (2,1,*) (2,2,*) (2,3,*) (3,1,*) (3,2,*)

(1,2,3) (1,3,2) (2,1,3) (2,3,1) (3,1,2) (3,2,1)


 Are complexitatea exponenţială, in cele mai multe cazuri fiind ineficientă. Ea
insa nu poate fi înlocuită cu alte variante de rezolvare mai rapide în situaţia în
care se cere determinarea tuturor soluţiilor unei probleme.

 Se foloseşte în rezolvarea unor probleme cum ar fi :


◦ Generarea permutărilor de n elemente
◦ Generarea aranjamentelor
◦ Generarea combinărilor
◦ Generarea partiţiilor unei mulţimi
◦ Problema celor N dame
◦ Produsul cartezian a N mulţimi
◦ Problema Comis-voiajorului
◦ Problema plăţii unei sume S utilizând N tipuri de monede
◦ Problema colorării hărților
Etape in proiectarea algoritmului:

1. Se alege modul de reprezentare a solutiilor

2. Se identifica spatiul de cautare si se stabilesc multimile A1,…,An si


ordinea in care sunt parcurse

3. Din restrictiile problemei se deduc conditiile pe care trebuie sa le


satisfaca solutiile partiale pentru a fi valide. Aceste conditii sunt de
regula denumite conditii de continuare.

4. Se stabileste criteriul in baza caruia se decide daca o solutie


partiala este solutie finala
Exemplu: Generarea permutărilor

1. Reprezentarea solutiei: fiecare permutare este un vector


x=(x1,x2,…xn) care satisface xi<>xj pentru orice i<>j

2. Multimile A1,…,An : {1,2,…,n}. Fiecare multime este prelucrata in


ordinea naturala a elementelor (de la 1 la n)

3. Conditii de continuare: o solutie partiala (x1,x2,…,xk) trebuie sa


satisfaca xk<>xi pentru orice i<k

4. Criteriu pentru a decide cand o solutie partiala este solutie finala:


k=n (au fost completate toate cele n componente)
 Metoda se aplica astfel:
 1) se alege prima valoare din A1 si i se atribuie lui x[1]
 2) se presupun generate elementele x[1]…x[k], cu valori din A1…Ak; pentru
generarea lui x[k+1] se alege primul element din Ak+1 (dacă există) si pentru
care se testează îndeplinirea condiţiilor de continuare
 Pot apărea următoarele situaţii:
 a) x[k+1] există. Daca s-a ajuns la o soluţie (k = n), atunci această soluție
se tipărește. Daca nu s-a ajuns la o soluţie, se consideră generate
x[1],x[2],…,x[k], x[k+1].
 b) x[k+1] nu există. Se consideră generate x[1], x[2],…,x[k-1]. Se va relua
căutarea de la elementul următor lui x[k] din Ak. Daca nu se găseşte nici o
valoare în Ak care să îndeplinească condiţiile de continuare, se revine la
elementul x[k-1] şi se reia algoritmul pentru o nouă valoare a acestuia.
 Algoritmul se încheie când au fost luate in considerare toate elementele din A1.
 Dacă mulţimile A1, A2,…An au acelaşi număr k de elemente, timpul necesar de
execuţie al algoritmului este k la puterea n. Dacă mulţimile A1, A2,…An nu au
acelaşi număr de elemente, atunci se notează cu „m” minimul cardinalelor
mulţimilor A1…An si cu „M”, maximul. Timpul de execuţie este situat în
intervalul [m la puterea n .. M la puterea n]
 Implementarea metodei se face utilizând structura de STIVA
 Elementele x1, x2, xn sunt într=o stivă ST.
 Găsirea elementului xk+1 determină urcarea în stivă pe nivelul k+1, în caz
contrar se coboară pe nivelul k-1.
 În cazul în care se ajunge pe nivelul 0 algoritmul se termină.

 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).

Două dame nu se pot găsi pe aceeași linie, coloană sau diagonală.


Două dame se găsesc pe aceeași linie daca st[i] = st[j]
Două dame se găsesc pe aceeași diagonală daca | st[i] - st[j] | = | i-j |
Cele două soluții pentru n=4 sunt:
St[1]=3 St[1]=2
St[2]=1 St[2]=4
St[3]=4 St[3]=1
St[4]=2 St[4]=3
1 2 3 4 1 2 3 4
1 D 1 D
2 D 2 D
3 D 3 D
4 D 4 D
 Fiecare linie contine exact o regina
 Fiecare coloana contine exact o regina
 Fiecare diagonala contine cel mult o regina

 Daca n<=3 nu are solutie


 Daca n=4 sunt 2 solutii
 Pe masura ce n creste numarul solutiilor creste (pt n=8 sunt 92 solutii)

 k – linia pe care e plasata dama


 st[k] – coloana pe care e plasata dama

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.

 O partitie a multimii {1,2,…n} se poate reprezenta sub forma unui vector st cu n


componente
 St[i]=k elementul i apartine submultimii k a partitiei
 Exemplu:
 A={1,2,3} Daca st={1,2,2} atunci el reprezinta submultimea {1} {2,3}
 O partitie a unei multimi cu n elemente este formata din cel mult n multimi
disjuncte. => St[i] apartine multimii {1,2,…n}
 Conventie (pentru a se evita repetarea partitiilor)
 St[1] ia numai valoarea 1 => elementul 1 va apartine doar submultimii 1
 St[2] ia numai valoarile 1,2 => elementul 1 va apartine doar submultimii 1 sau
2
 St[1] ia numai valoarile 1,2,…n => elementul 1 va apartine doar submultimii 1
sau 2 sau…n
 Elementul st[k] se poate majora pana la maximul dintre precedentele plus 1
 Avem solutie cand am gasit succesorul de pe nivelul n
program partitii; procedure tipar;
type stiva=array [1..100] of integer; var i:integer;
begin
var st:stiva; max,p,i,j,n,k,l:integer; as,ev:boolean;
l:=l+1; writeln('Solutia ',l);
procedure init(k:integer;var st:stiva); max:=st[1];
begin for i:=2 to n do
st[k]:=0; if max<st[i] then max:=st[i];
writeln(‘ PARTITIE ’);
end;
for j:=1 to max do
procedure succesor(var as:boolean;var st:stiva;k:integer); begin
begin for i:=1 to n do
if k=1 then max:=1 else begin max:=st[1] if st[i]=j then write(i, ‘ ‘);
for i:=2 to k-1 do if max<st[i] then max:=st[i] end; writeln;
end;
if (st[k]<max+1) and (st[k]<k) then
end;
begin begin
st[k]:=st[k]+1; l:=0;
as:=true; write('n='); read(n);
end k:=1;
init(k,st);
else as:=false while k>0 do
end; begin
procedure valid(var ev:boolean;st:stiva;k:integer); repeat
var i:integer; succesor(as,st,k);
if as then valid(ev,st,k)
begin
until (not as) or (as and ev);
ev:=true; if as then
end; if solutie(k) then tipar
function solutie(k:integer):boolean; else
begin
begin
k:=k+1;
solutie:=(k=n); init(k,st)
end; end
else k:=k-1; end; end.
 Se dau: suma s si n tipuri de monede avand valori de a1,a2,...an lei. Se cer toate
modalitatile de plata a sumei s utilizand aceste monede.

 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

 1->7->3->4 Timisoara Constanta


 1->2->3->4 Bucuresti
 1->6->5->3->4
 1->6->5->2->3->4
 Legaturile existente intre orase sunt date in matricea A (nxn):
 A[i,j]=1 daca exista drum intre orasele i si j
 A[i,j]=0 daca nu exista drum intre orasele i si j
 Matricea A este simetrica a[i,j]=a[j,i]
 Elementele matricei pot fi 0 si 1

 Un succesor (intre 2 si n) este valid daca sunt indeplinite conditiile de


continuare:
 Nu s-a mai trecut (pana la acel moment) prin orasul respectiv, k (elemente
distincte)
 Exista drum intre orasul aflat pe nivelul k-1 si nivelul k
 Daca succesorul se gaseste pe nivelul n, exista drum de la orasul n la orasul 1

 Algoritmul se termina cand se ajunge din nou la nivelul 1


procedure tipar;
program comis_voiajor;
var i:integer;
type stiva=array [1..100] of integer; begin
var st:stiva; p,i,j,n,k,l:integer; as,ev:boolean; l:=l+1; writeln('Solutia ',l);
a:array[1..20,1..20] of integer; for i:=1 to n do
write(st[i], ‘ ‘);
procedure init(k:integer;var st:stiva);
writeln;
begin end;
st[k]:=1; end;
end; begin
l:=0;
procedure succesor(var as:boolean;var st:stiva;k:integer);
write('n='); read(n);
begin for i:=1 to n do
if st[k]<n then for j:=1 to i-1 do
begin begin
st[k]:=st[k]+1; read(a[I,j]);
a[j,i]:=a[I,j];
as:=true;
end;
end st[1]=1; k:=2;
else as:=false init(k,st);
end; while k>0 do
procedure valid(var ev:boolean;st:stiva;k:integer); begin
repeat
var i:integer; succesor(as,st,k);
begin if as then va+lid(ev,st,k)
ev:=true; until (not as) or (as and ev);
if a[st[k-1],st[k]]=0 then ev:=false if as then
if solutie(k) then tipar
else
else
for i:=1 to k-1 do if (st[i]=st[k]) then ev:=false; begin
if (k=n) and (a[1,st[k]=0) then ev:=false; k:=k+1;
end; init(k,st)
function solutie(k:integer):boolean; end
else k:=k-1; end; end.
begin solutie:=(k=n); end;
 Fiind data o harta cu n tari, se cer toate solutiile de colorare a hartii, utilizand
maxim 4 culori, astfel incat doua tari cu frontiera comuna sa fie colorate
diferit. Este demonstrat faptul ca sunt suficiente numai 4 culori astfel incat
orice harta sa poata fi colorata.
 Problema matematica: orice harta poate fi colorata utilizand cel mult 4 culori
(rezultat demonstrat in 1976 de catre Appel and Haken)

 a[i,j]=1 daca tara i este vecina cu tara j


 a[i,j]=0 daca tara i nu este vecina cu tara j
 Exemplu pentru n=5
 A=[1 1 1 1 0; 1 1 1 0 1; 1 1 1 0 1; 1 1 1 1 1]
 O solutie posibila:
 st[1]=1 st[2]=2 st[3=1 st[4]=3 st[5]=4
 Matricea A este simetrica
 K - țara
 st[k] - culoarea țării k
program colorare_harti; 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..20,1..20] of integer; for i:=1 to n do
procedure init(k:integer;var st:stiva); writeln(‘tara ’,i, ‘ are culoarea ’,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
if st[k]<4 then
for j:=1 to i-1 do
begin begin
st[k]:=st[k]+1; read(a[I,j]);
as:=true; a[j,i]:=a[I,j];
end end;
k:=1;
else as:=false
init(k,st);
end; while k>0 do
procedure valid(var ev:boolean;st:stiva;k:integer); begin
var i:integer; repeat
begin succesor(as,st,k);
if as then valid(ev,st,k)
ev:=true; until (not as) or (as and ev);
for i:=1 to k-1 do if as then
if (st[i]=st[k]) and (a[i,k]=1) then ev:=false; if solutie(k) then tipar
end; else
begin
function solutie(k:integer):boolean;
k:=k+1;
begin init(k,st)
solutie:=(k=n); end
end; else k:=k-1; end; end.

S-ar putea să vă placă și