Sunteți pe pagina 1din 3

Algoritmul general al metodei Backtracking

Pentru evitarea generǎrii combinaţiilor neconvenabile se procedeazǎ astfel:


Presupunem cǎ s-au gǎsit valori pentru componentele x1x2... xk-1 (au rǎmas de determinat
valorile pentru xk…xn). ne ocupǎm în continuare de componenta xk. Paşii urmaţi pentru
determinarea unei valori pe poziția k sunt următorii:
1. Pentru început, pentru xk nu s-a testat încǎ nici o valoare (xk are valoarea inițială).
2. Se verificǎ dacǎ existǎ valori netestate pentru xk .
a) În caz afirmativ, se trece la pasul 3.
b) Altfel, se revine la componenta anterioarǎ, xk-1; se reia pasul 2 pentru k=k-1.
3. Se alege prima valoare v dintre cele netestate încǎ pentru xk.
4. Se verificǎ dacǎ acestǎ combinaţie parţialǎ cu valori pt elementele x1x2... xk-1 și xk ne
poate conduce la un rezultat (dacǎ sunt îndeplinite anumite condiţii de continuare).
a) Dacǎ valoarea aleasǎ este bunǎ se trece la pasul 5.
b) Altfel, se rǎmâne pe aceeaşi poziţie k şi se reia cazul 2.
5. Se verificǎ dacǎ s-a obţinut o soluţie .
a) În caz afirmativ, se tipǎreşte aceastǎ soluţie şi se rǎmâne la aceeaşi componentǎ
xk, reluându-se pasul 2.
b) Altfel se reia altgoritmul pentru urmǎtoarea componentǎ (se trece la pasul 1
pentru k=k+1).
Algoritmul începe prin stabilirea unei valori pentru componenta x1(k=1) şi se încheie când
pentru aceasta am testat toate valorile posibile şi conform pasului 2b) ar trebui sǎ revenim la
componenta anterioarǎ, care în aceast caz nu existǎ.
Rezumând, metoda Backtracking se foloseşte în rezolvarea problemelor care îndeplinesc
condiţiile:
- soluţia poate fi pusǎ sub forma unui vector S=x1x2…xn, unde xi  Ai , i  1,..., n;
- mulţimile Ai sunt finite şi ordonate (pentru a lua în considerare toate valorile posibile).
☺Observaţii: - în unele probleme n variazǎ de la o soluţie la alta;
- mulţimile Ai pot coincide;
- metoda Backtracking oferǎ toate soluţiile.

Înainte de a scrie programul care ne va obţine soluţiile, trebuie sǎ stabilim unele detalii cu
privire la:
- vectorul soluţie (SOLUTIE(k)) – câte componente are (Exemplu pentru permutări
vectorul soluție are n valori)
- mulţimea de valori posibile (EXISTA(k)) pentru fiecare componentǎ (sunt foarte
importante limitele acestei mulţimi). (Exemplu pentru permutări x[k]<=n, deci, x[k] ia valori de
la 1 la n , pentru orice valoare k de la 1 la n)
- condiţiile de continuare (VALID (K)) (condiţiile ca o valoare x[k]sǎ fie acceptatǎ).
). (Exemplu pentru permutări, fiecare element x[k] ales la pasul k trebuie să fie diferit de
elementul precedent x[k] # x[i] oricare i de la 1 la k-1, pentru orice valoare k de la 1 la n)
Funcţia EXISTA(k) verificǎ dacǎ ultima valoare aleasǎ pentru componenta xk nu a atins
limita maximǎ admisǎ (indicele de valoare maximǎ). Întrucât elementele sunt testate în ordine,
acest lucru este echivalent cu a verifica dacǎ mai avem valori netestate încǎ pentru aceastǎ
componentǎ.
Funcţia VALID(k) verificǎ dacǎ valoarea aleasǎ pentru x[k] îndeplineşte condiţiile de
continuare, deci dacǎ aceastǎ combinaţie parţialǎ v1v2…vk poate sǎ conducǎ la o soluţie.
☺Observaţie: La implementarea acestei funcţii se identificǎ acele cazuri în care acest lucru
este posibil, RETURNÂND VALOAREA 0 !!!.

Funcţia SOLUTIE(k) verificǎ dacǎ s-a ajuns la o soluţie finalǎ (ÎN MULTE
PROBLEME LUCRATE PANĂ ACUM k==n).
Procedura TIPAR(k) tipǎreşte o soluţie.
Algoritmul propus este:
void BT()
{ int k;
K ← 1;
INIT(k);
while k>0 do
if (EXISTA(k))
{
x[k]=x[k]+1;
if VALID(k)
if SOLUTIE(k)
TIPAR(k)
else
{
K ← k+1;
INIT(k);
};
}
else
k ← k-1;
}

☺Observaţii: În situaţiile în care operaţiile relizate în procedurile enunţate sunt


simple, se poate renunţa la implementarea lor în aceastǎ formǎ, iar altgoritmul
general va conţine direct aceste operaţii.

De asemenea, trebuie sǎ avem în vedere cǎ algoritmul general se poate modifica şi adapta


în funcţie de problema rezolvatǎ.
Exemplu de implementare a algoritmului pentru generarea permutărilor mulțimii:
int x[100],n;
void INIT(int k)
{ x[k]=0;}
int EXISTA (int k)
{ void BT()
if(x[k]<n)return 1;else { int k;
return 0; k:=1;
} INIT(k);
int SOLUTIE (int k) while k>0 do
{ if (EXISTA(k))
if(k==n) return 1; {
else return 0; x[k]=x[k]+1;
} if (VALID(k) )
void TIPAR (int k) if (SOLUTIE(k) )
{ TIPAR(k);
int i; else
for (i=1;i<=k;i++) {
cout<<x[i]<<” “; k=k+1;
cout<<”\n”; INIT(k);
} };
int VALID(int k) }
{ else
int i; k=k-1;
for (i=1;i<k;i++) }
if (x[i]==x[k]) int main()
return 0; {cin>>n; BT();}
return 1;
}
Pentru o scriere mai rapidă, în practică nu vom folosi toate aceste funcții descrise mai sus.
Un algoritm mai scurt este:
int x[100],n;

void TIPAR (int k)


{
int i;
for (i=1;i<=k;i++)
cout<<x[i]<<” “;
cout<<”\n”;
}

int VALID(int k)
{
int i;
for (i=1;i<k;i++)
if (x[i]==x[k])
return 0;
return 1;
}

void BT()
{ int k;
k:=1;
x[k]=0;
while k>0 do
if (x[k]<n)
{
x[k]=x[k]+1;
if (VALID(k))
if (k==n)
TIPAR(k)
else
{
k=k+1;
x[k]=0;
};
}
else
k=k-1;
}
int main()
{
cin>>n;
BT();
}

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