Sunteți pe pagina 1din 4

Metoda Backtracking

Scopul utilizarii acestei metode


Aceasta metoda se foloseste in rezolvarea problemelor ce indeplinesc simultan urmatoarele conditii:
solutia lor poate fi pusa sub forma unui vector S=x1, x2,..., xn, cu x1 apartine lui A1, xn apartine
lui An;
multimile A1, A2,...An sunt multimi finite iar elementele lor se considera ca sunt intr-o ordine
bine stabilita;
nu se dispune de o solutie mai rapida.
Metoda backtracking urmareste fie determinarea tuturor solutiilor (cu scopul de a le
lista sau de a alege dintre ele una care optimizeaza o eventuala functie obiectiv data), fie obtinerea
unei solutii oarecare.
Prezentare generala
Metoda backtracking consta in urmatoarele:
se alege primul element x1 ce apartine multimii A1;
presupunand generate elementele x1, x2,..., xk apartinand multimilor A1, A2,...Ak se alege xk+1,
primul element disponibil din Ak+1 care indeplineste anumite conditii de continuare, aparand
astfel doua posibilitati:
a)elementul exista , se testeaza daca nu s-a ajuns la solutie, in caz afirmativ aceasta se tipareste, in
caz contrar, se considera generate x1, x2,.., xk+1 ;
b) elementul nu exista , situatie in care se considera generate elementele x1, x2,.., xk-1, reluinduse cautarea de la elementul urmator lui xk din Ak;
algoritmul se incheie cand au fost luate in consideratie toate elementele multimii A1
Implementarea metodei
se face folosind structura de stiva.
Astfel, elementele x1, x2,..., xk ni le imaginam intr-o stiva st. Gasirea elementului xk+1
determina urcarea in stiva pe nivelul k+1, contrar se coboara la nivelul k-1.
In situatia ajungerii la nivelul 0, algoritmul se termina.
1. Backtracking iterativ
La urcarea in stiva , pe nivelul la care am ajuns, se pune o valoare care nu se afla in
multimea considerata, dar de la care, la pasul urmator se ajunge la primul element din acea
multime (procedura INIT).
Pe un anumit nivel, gasirea elementului considerat se face de o procedura/functia numita
SUCCESOR.
Verificarea faptului ca acesta indeplineste conditiile de continuarea a algoritmului este
facuta de o procedura/functia numita VALID.
Testarea daca s-a ajuns la solutie este realizata de functia SOLUTIE.
Afisarea solutiei este realizata de procedura/functia TIPAR.
Aceste subprograme sunt diferite de la aplicatie la aplicatie, insa indiferent de aplicatie exista o parte fixa,
partea care implementeaza strategia generala backtracking:
k=1;
init(k,st);
while (k>0)
{ do {
succesor(as,st,k);
if (as) valid(ev,st,k);}
while (as || !(ev));
if (as)
if (solutie(k)) tipar
else
{k++; init(k,st);}
1

else k--; }
Aplicatie: Problema celor n dame
Se considera o tabla de sah de dimensiuni n*n. Se cer toate solutiile de aranjare a n dame astfel incat sa
nu se atace reciproc (sa nu fie pe aceeasi linie/coloana sau pe diagonala).
init : nivelul k al stivei este initializat cu 0;
succesor : se mareste cu 1 valoarea aflata pe nivelul k al stivei in situatia in care aceasta este mai
mica decat n si atribuie variabilei as valoarea true; in caz contrar, atribuie variabilei as valoarea
false;
valid : valideaza valoarea pusa pe nivelul k al stivei, verificand daca nu avem doua dame pe
aceeasi linie/coloana ( st(k) = st(i) ), sau daca nu avem doua dame pe aceeasi diagonala ( |st(k)
st(i)| = | k-i |, caz in care variabilei ev i se atribuie valoarea false; in caz contrar, variabilei ev i se
atribuie true.
solutie : verifica daca stiva a fost completata pana la nivelul n inclusiv;
tipar : tipareste ( afiseaza ) o solutie.
#include <iostream.h>
int n, st[100], as, ev;
void init(int k)
{st[k]=0;}
void succesor(int &as, int st[100], int k)
{ if (st[k]<n) {st[k]++; as=1;}
else as=0;
}
void valid(int &ev, int st[100], int k)
{int i;
ev=1;
for (i=1; i<=k-1; i++)
if (st[k]==st[i]) ev=0;
}
int solutie(int k)
{return k==n+1;
}
void tipar ()
{for(int i=1; i<=n; i++)
cout<<st[i];
cout<<endl;
}
void main()
{cout<<n=;cin>>n;
//rutina generala backtracking
.....
}

2. Backtracking recursiv
Procedurile si functiile folosite sunt, in general, aceleasi cu cele de la backtracking iterativ, cu doua mici
exceptii:
Succesor nu mai este procedura ci functie booleana(deci, dispare variabila as);
Rutina backtracking se transforma in procedura, care se apeleaza prin back(1).
Principiul de functionare al procedurii back, corespunzator unui nivel k, este:
In situatia in care avem o solutie, o tiparim si revenim pe nivelul anterior;
In caz contrar, se initializeaza nivelul si se cauta un succesor;
Cand am gasit unul, verificam daca este valid; procedura se autoapeleaza pentru k+1, in caz
contrar urmand a se continua cautarea succesorului;
Daca nu avem succesor, se trece pe nivelul inferior(k-1) prin iesirea din procedura/functia back.
void back(int k)
{if (solutie(k)) tipar();
else
{init(k,st);
while (succesor(st,k))
if (valid(st,k)) back(k+1);
}
Problema celor n dame:
#include <iostream.h>
int n, st[100];
void init(int k)
{st[k]=0;}
int succesor(int st[100], int k)
{ if (st[k]<n) {st[k]++; return 1;}
else return 0;
}
int valid(int st[100], int k)
{int i, ev=1;
for (i=1; i<=k-1; i++)
if (st[k] == st[i]) ev:=0;
return ev;
}
int solutie(int k)
{return k == n+1;
}
void tipar ()
{for(int i=1;i<=n;i++)
cout<<st[i];
cout<<endl;
}
void back(int k)
{if (solutie(k)) tipar();
else
{init(k,st);
while (succesor(st,k))
if (valid(st,k)) back(k+1);
}
void main()
{cout<<n=; cin>>n; back(1);}
3

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