Aceasta tehnica se foloseste in rezolvarea problemelor care indeplinesc simultan urmatoarele conditii:
Multimile A1, A2, ., An sunt multimi finite, iar elementele lor se presupune ca se gasesc intr-o relatie de ordine bine stabilita;
La intalnirea unei astfel de probleme, daca nu se cunoaste aceasta tehnica, suntem tentati sa generam toate elementele produsului cartezian A1*A2*.*An si fiecare element sa fie testat daca este solutie. Rezolvand problema in acest mod, timpul de executie este atit de mare, incat poate fi considerat infinit, algoritmul neavand nici o valoare practica.
Tehnica Backtracking are la baza un principiu extrem de simplu:
Se construieste solutia pas cu pas: x1, x2, ., xn;
Daca se constata ca pentru o valoare aleasa nu avem cum sa ajungem la o solutie, se renunta la acea valoare si se reia cautarea din punctul in care am ramas.
Concret:
Se alege primul element x1IA1;
Presupunand generate elementele x1, x2, ., xk apartinand multimilor A1, A2, ., An se alege (daca exista) xk+1, primul element disponibil din multimea Ak+1, apar 2 posibilitati:
Nu s-a gasit un astfel de element, caz in care se reia cautarea considerand generate elementele x1, x2, ., xk-1 iar aceasta se reia de la urmatorul element al multimii Ak, ramas netestat;
A fost gasit, caz in care se testeaza daca acesta indeplineste anumite conditii de continuare, aparand astfel doua posibilitati:
2.1) le indeplineste, caz in care se testeaza daca s-a ajuns la solutie si apar, din nou, doua posibilitati:
2.1.1) s-a ajuns la solutie, se tipareste solutia si se reia algoritmul considerand generate elementele x1, x2, ., xk (se cauta in continuare un alt element al multimii Ak+1 ramas netestat).
2.1.2) nu s-a ajuns la o solutie, caz in care se reia algoritmul considerand generate elementele x1, x2, ., xk+1 si se cauta un prim element xk+2IAk+2
2.2) nu le indeplineste, caz in care se reia algoritmul considerand generate elementele x1, x2, ., xk, iar elementul xk+1 se cauta intre elementele multimii Ak+1 ramase netestate.
Algoritmul se termina atunci cand nu mai exista nici un element x1IA1 netestat.
Tehnica Backtracking are a rezultat obtinerea tuturor solutiilor problemei. In cazul in care se cere o singura solutie se poate forta oprirea atunci cand solutia a fost gasita.
Pentru usurarea intelegerii metodei, vom prezenta o rutina unica, aplicabila oricarei probleme, rutina care utilizeaza notiunea de stiva. Rutina va apela proceduri si functii care au intotdeauna acelasi nume si parametrii si care din punct de vedere al metodei, realizeaza acelasi lucru. Sarcina programatorului este de a scrie explicit, pentru fiecare problema in parte, procedurile si functiile apelate in rutina backtracking. Evident, o astfel de abordare conduce la programe lungi. Nimeni nu ne opreste, ca dupa intelegerea metodei, sa scriem programe scurte, specifice fiecarei probleme in parte.
Se va folosii o procedura init_nivel care va initializa nivelul curent din stiva. Ea va avea doi parametrii: o stiva st si nivelul curent din stiva, k. Gasirea urmatorului element al multimii Ak se face cu ajutorul procedurii succesor(st,k,as). Parametrul as (am succesor) este o variabila booleana care va avea valoarea true daca s-a gasit un succesor si false in caz contrar. Odata ales un element trebuie vazut daca acesta indeplineste conditiile problemei. Acest lucru se va testa in procedura valid(st,k,ev). Testul daca s-a ajuns sau nu la o solutie finala se face cu ajutorul functiei solutie, iar o solutie se afiseaza cu ajutorul procedurii tip_sol.
Rutina backtracking este urmatoarea:
k:=1;
init_nivel(st,k);
while k>0 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
Probleme:
1. Generarea permutarilor:
Se citeste un numar natural n. Sa se genereze toate permutarile multimii .
uses crt;
type stiva=array[1..10] of integer;
var st:stiva;
n,i,k:integer;
as,ev:boolean;
procedure init_nivel(var st:stiva;k:integer);
begin
st[k]:=0;
end;
procedure succesor(var st:stiva;k:integer; var as:boolean);
begin
if st[k]<n then
begin
as:=true;
st[k]:=st[k]+1;
end
else
as:=false;
end;
procedure valid(st:stiva; k:integer; var ev:boolean);
begin
ev:=true;
for i:=1 to k-1 do
if st[i]=st[k] then
ev:=false;
end;
function solutie(st:stiva; k:integer):boolean;
begin
if k=n then
solutie:=true
else
solutie:=false;
end;
procedure tipar;
begin
for i:=1 to n do
write(st[i],' ');
writeln;
end;
begin
clrscr;
write('n=');
read(n);
k:=1;
init_nivel(st,k);
while k>0 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
readln;
end.
2. Generarea aranjamentelor
Se citesc n si p numere naturale. Se cere sa se genereze toate submultimile multimii de p elemente. Doua multimi cu aceleasi elemente, la care ordinea acestora difera, sunt considerate distincte.
Din analiza problemei rezulta urmatoarele:
Stiva are inaltimea p
Fiecare nivel ia valori intre 1 si n
Elementele plasate pe diferite niveluri trebuie sa fie distincte.
uses crt;
type stiva=array[1..10] of integer;
var st:stiva;
n,p,i,k:integer;
as,ev:boolean;
procedure init_nivel(var st:stiva;k:integer);
begin
st[k]:=0;
end;
procedure succesor(var st:stiva;k:integer; var as:boolean);
begin
if st[k]<n then
begin
as:=true;
st[k]:=st[k]+1;
end
else
as:=false;
end;
procedure valid(st:stiva; k:integer; var ev:boolean);
begin
ev:=true;
for i:=1 to k-1 do
if st[i]=st[k] then
ev:=false;
end;
function solutie(st:stiva; k:integer):boolean;
begin
if k=p then
solutie:=true
else
solutie:=false;
end;
procedure tipar;
begin
for i:=1 to p do
write(st[i],' ');
writeln;
end;
begin
clrscr;
write('n=');
read(n);
writ('p=');
realn(p);
k:=1;
init_nivel(st,k);
while k>0 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
readln;
end.
Generarea combinarilor:
Se citesc n, p numere naturale, cu n>=p. Se cere sa se genereze toate submultimile cu p elemente al submultimii . Doua submultimi se considera egale daca si numai daca au aceleasi elemente, indiferent de ordinea in care ele apar.
Pentru rezolvarea problemei trebuie tinut cont de urmatoarele:
Stiva are inaltimea p
Elementele aflate pe nivele diferite ale stivei trebuie sa fie distincte
Nivelul k al stivei ia valori intre 1 si n-p+k
Este necesar ca pe nivelul k sa se afle o valoare mai mare decat pe nivelul k-1.
uses crt;
type stiva=array[1..10] of integer;
var st:stiva;
n,p,i,k:integer;
as,ev:boolean;
procedure init_nivel(var st:stiva;k:integer);
begin
st[k]:=0;
end;
procedure succesor(var st:stiva;k:integer; var as:boolean);
begin
if st[k]<n-p+k then
begin
as:=true;
st[k]:=st[k]+1;
end
else
as:=false;
end;
procedure valid(st:stiva; k:integer; var ev:boolean);
begin
ev:=true;
for i:=1 to k-1 do
if st[i]=st[k] then
ev:=false;
if k>1 then
if st[k]<st[k-1] then
ev:=false;
end;
function solutie(st:stiva; k:integer):boolean;
begin
if k=p then
solutie:=true
else
solutie:=false;
end;
procedure tipar;
begin
for i:=1 to p do
write(st[i],' ');
writeln;
end;
begin
clrscr;
write('n=');
read(n);
writ('p=');
realn(p);
k:=1;
init_nivel(st,k);
while k>0 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
readln;
end.
Problema colorarii hatilor:
Fiind data o harta cu n tari, se cer toate posibilitatile de colorare a hartii, utilizand cel mult 4 colori, astfel incat doua tari cu frontiera comuna sa fie colorate diferit. Harta este furnizata programului cu ajutorul unei matrici Am,n
Matricea A este simetrica.
uses crt;
type stiva=array[1..10] of integer;
matrice=array[1..10,1..10] of integer;
var st:stiva;
n,p,i,k:integer;
as,ev:boolean;
a:matrice;
procedure init_nivel(var st:stiva;k:integer);
begin
st[k]:=0;
end;
procedure succesor(var st:stiva;k:integer; var as:boolean);
begin
if st[k]<4 then
begin
as:=true;
st[k]:=st[k]+1;
end
else
as:=false;
end;
procedure valid(st:stiva; k:integer; var ev:boolean);
begin
ev:=true;
for i:=1 to k-1 do
if (st[i]=st[k]) and (a[i,k]=1) then
ev:=false;
end;
function solutie(st:stiva; k:integer):boolean;
begin
if k=n then
solutie:=true
else
solutie:=false;
end;
procedure tipar;
begin
for i:=1 to n do
write(st[i],' ');
writeln;
end;
begin
clrscr;
write('n=');
read(n);
for i:=1 to n do
a[i,i]:=1;
for i:=1 to n do
for j:=i+1 to n do
begin
readln(a[i,j]);
a[j,i]:=a[i,j];
end;
k:=1;
init_nivel(st,k);
while k>0 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
readln;
end.
Problema comis-voiajorului:
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.
Legaturile dintre orase sunt date de matricea Am,n
Matricea A este simetrica.
Pentru rezolvarea problemei vom folosii o stiva st. La baza stivei (nivelul 1) se incarca numarul 1. Algoritmul continua In acest mod pana cand se ajunge din nou la nivelul 1. Un succesor intre 2 si n, aflat pe nivelul k al stivei, este considerat valid daca sunt indeplinite urmatoarele conditii:
Nu s-a mai trecut prin orasul simbolizat de succesor, deci acesta nu se regaseste in stiva
Exista drum intre orasul aflat pe nivelul k-1 si cel aflat pe nivelul k
Daca succesorul se gaseste pe nivelul n, sa existe drum aflat intre el si orasul 1.
uses crt;
type stiva=array[1..10] of integer;
var st:stiva;
n,p,i,k:integer;
as,ev:boolean;
procedure init_nivel(var st:stiva;k:integer);
begin
st[k]:=1;
end;
procedure succesor(var st:stiva;k:integer; var as:boolean);
begin
if st[k]<n then
begin
as:=true;
st[k]:=st[k]+1;
end
else
as:=false;
end;
procedure valid(st:stiva; k:integer; var ev:boolean);
begin
ev:=true;
if a[st[k-1],st[k]]=0 then
ev:=false
else
for i:=1 to k-1 do
if (st[i]=st[k]) then
ev:=false;
if (k=n) and (a[1,st[k]]=0) then
ev:=false;
end;
function solutie(st:stiva; k:integer):boolean;
begin
if k=n then
solutie:=true
else
solutie:=false;
end;
procedure tipar;
begin
for i:=1 to n do
write(st[i],' ');
writeln;
end;
begin
clrscr;
write('n=');
read(n);
for i:=1 to n do
for j:=1 to i-1 do
begin
readln(a[i,j]);
a[j,i]:=a[i,j];
end;
st[1]:=1;
k:=2;
init_nivel(st,k);
while k>1 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
readln;
end.
Partitiile unui numar natural:
Se citeste un numar natural n. Se cere sa se tipareasca toate modurile de descompunere a sa ca suma de numere naturale.
Ex: n=4. Avem: 1111, 112, 121, 13, 211, 22, 31, 4.
Ordinea numerelor din suma este importanta. Astfel, se tipareste 112 dar si 121, 211.
Pentru rezolvare, vom observa ca nivelul 1 al stivei ia valori intre 1 si n, nivelul 2 ia valori intre 1 si n-1, in general, nivelul k ia valori intre 1 si n-k+1 (succesor). O solutie partiala este valida daca suma elementelor pe care le contine este mai mica sau egala cu n (valid) si am obtinut o solutie cand aceasta suma este egala cu n.
uses crt;
type stiva=array[1..10] of integer;
var st:stiva;
n,p,i,k:integer;
as,ev:boolean;
procedure init_nivel(var st:stiva;k:integer);
begin
st[k]:=0;
end;
procedure succesor(var st:stiva;k:integer; var as:boolean);
begin
if st[k]<n-k+1 then
begin
as:=true;
st[k]:=st[k]+1;
end
else
as:=false;
end;
procedure valid(st:stiva; k:integer; var ev:boolean);
begin
s:=0;
for i:=1 to k do
s:=s+st[i];
if s<=n then
ev:=true
else
ev:=false;
end;
function solutie(st:stiva; k:integer):boolean;
begin
if s=n then
solutie:=true
else
solutie:=false;
end;
procedure tipar;
begin
for i:=1 to p do
write(st[i],' ');
writeln;
end;
begin
clrscr;
write('n=');
read(n);
k:=1;
init_nivel(st,k);
while k>0 do
begin
repeat
succesor(st,k,as);
valid(st,k,ev);
until ((as=true) and (ev=true)) or (as=false);
if as=true then
if solutie(st,k) then tipar
else
begin
k:=k+1;
init_nivel(st,k);
end
else
k:=k-1;
end;
end.
Tema:
Sa se genereze toate aranjamentele de n luate cate p cu proprietatea ca diferenta in modul dintre oricare doua numere consecutive este cel putin egala cu o valoare v citita de la tastatura.
Sa se genereze toate permutarile lexicografice ale unui cuvant citit de la tastatura.
Sa se genereze toate partitiile multimii
Se citeste de la tastatura un numar natural n. Sa se genereze toate numerele intregi a caror reprezentare in baza 2 au acelasi numar de cifre 0 (semnificative) si respectiv si respectiv 1 ca si reprezentarea in baza 2 a numarului n.
Ex.: Pentru n=53 se vor afisa numerele 39, 43, 45, 46, 51, 53, 54, 57, 58, 60.
Politica de confidentialitate |
.com | Copyright ©
2024 - Toate drepturile rezervate. Toate documentele au caracter informativ cu scop educational. |
Personaje din literatura |
Baltagul – caracterizarea personajelor |
Caracterizare Alexandru Lapusneanul |
Caracterizarea lui Gavilescu |
Caracterizarea personajelor negative din basmul |
Tehnica si mecanica |
Cuplaje - definitii. notatii. exemple. repere istorice. |
Actionare macara |
Reprezentarea si cotarea filetelor |
Geografie |
Turismul pe terra |
Vulcanii Și mediul |
Padurile pe terra si industrializarea lemnului |
Termeni si conditii |
Contact |
Creeaza si tu |