Sunteți pe pagina 1din 4

Metoda backtracking

Spațiul soluțiilor
 În multe probleme soluțiile pot fi descrise ca vectori cu n elemente x=( x 1 , x 2 , … , x n ) unde
x i ∈ S i , i=1 , … , n
 S=S 1 × S 2 × …× S n= { x=( x 1 , x 2 , … , x n )∨x i ∈ S i }  spațiul soluțiilor
 i=1 , n : card ¿, și pe Si este definită o relație de ordine totală
 φ : S → { da , nu } funcție de validare
 R={ x ∈ S∨φ ( x )=da } mulțimea soluțiilor rezultat
 φ ( x )=da ⟺ x ∈ R
 φ k : S1 × S2 ×… × S k → { da , nu } funcții de validare parțială
 φ k−1=da ⇒ se poate adăuga un element x k ∈ S k cu φ k =da
 φ k−1=nu ⇒ nu se poate adăuga un element x k ∈ S k cu φ k =da

Backtracking – căutare completă


 Metodă lentă, costisitoare, complexitate mare
◦ Verificarea ~tuturor elementelor spațiului soluțiilor S=S 1 × S 2 × …× S n
◦ x=( x 1 , x 2 , … , x n ), x i ∈ S i, i=1 , n
◦ φ ( x )=da
◦ φ k - condiții de continuare
◦ x se construiește element cu element
◦ x i primește o valoare din Si numai după ce toate elementele anterioare au primit valori acceptabile (
x 1 , x 2 , … , x i−1)
◦ dacă φ i ( x 1 , x 2 ,… , x i )=da ⇒ se trece la elementul i+1
◦ altfel se alege altă valoare pentru x i
◦ valoarea aleasă pentru x i e consumată ⇒ C i mulțimea valorilor consumate
◦ dacă nu mai sunt valori disponibile se revine la elementul anterior
◦ φ i ( x 1 , x 2 ,… , x i )=da nu garantează obținerea unei soluții rezultat
Backtracking - reprezentare date
 Configurație curentă v1 … vn
v … v x … x
( 1 i−1
C 1 … Ci−1 C i | i

n
∅ )
 Configurație soluție
( C1 … Cn |)
x1 … x n

x … xn
Configurație inițială 1
(|
∅ ∅ ∅ )
 Configurație finală
(|S1 ∅ ∅ )
 Rezolvare problemă:

Configurație inițială → configurație soluție →…→configurație soluție → configurație finală

Backtracking – operații
 Atribuie și avansează - x i ← v i , φi ( x1 , x 2 , … , xi ) =da,C i ← Ci ∪ { v i }
… v i−1 xi x i+1 … … v i−1 vi x i+1 …
( |
… C i−1 C i ∅ …

) (
… C i−1 Ci ∪ { v i } ∅ … | )
 Încercare eșuată - x i ← v i , φi ( x1 , x 2 , … , xi ) =nu ,C i ← Ci ∪ { v i }
x i rămâne neatribuit
… v i−1 xi x i+1 … … v i−1 xi x i+1 …
( |
… C i−1 C i ∅ …
=¿=
) (
… C i−1 C i ∪ { v i } ∅ … | )
 Revenire după o încercare eșuată, cu epuizarea variantelor ( C i=Si )
… v i−1 xi xi +1 … … v i−2 x i−1 x i …
( |
… C i−1 Si ∅ …

) ( |
… C i−2 Ci −1 ∅ … )
 Revenire după construirea unei soluții
… v n−1 v n … v n −1 x n
( … C n−1 C n

|) (
… C n−1 Cn |)
Backtracking - implementare recursivă
 Metoda este de natură recursivă, deci ușor de implementat recursiv
 Forma recursivă generală
 backtracking(i)
 dacă i==n+1
  retine_solutia()
 altfel
  pentru fiecare element j din S i
  x[i]=j;
  daca posibil(i)
  call backtracking(i+1)
Backtracking – implementare iterativă
 inițializare S1 , S 2 , … , S n
 C i=∅ ,i=1, n //construire configurație inițială
 i=1
 cât timp i>0 //cât timp configurația nu e finală
◦ dacă i=¿ n+1 //configurație de tip soluție?
 reține soluția Sol= ( x1 , x2 , … , xn )
 i=i−1 //revenire după construirea unei soluții
◦ altfel
 dacă C i ≠ S i //mai sunt valori neconsumate
 alege o valoare vi ∈ Si −Ci
 C i=Ci ∪ { vi }
 dacă ( v ¿ ¿1 , v 2 , … , v i−1 , v i) ¿ satisface condițiile de continuare
 x i=vi //atribuie și avansează
 i=i +1
//altfel încercare eșuată
 altfel //revenire
 C i=∅
 i=i−1

Backtracking – variantă
 Particularități ale unor probleme
◦ Si - progresii aritmetice cu termen inițial a i, rația r i și termen final si
 uneori a i=1, r i=1
◦ toate Si sunt identice cu mulțimea { 1,2 , … , n }
◦ Avantaje
◦ nu trebuie memorate explicit mulțimile Si și C i
◦ alegerea unui element neconsumat este ușoară
◦ a i, a i+r , a i+2∗r ,  ai +3∗r , …, , x i−r , x i, x i+ r , … , si
 i=1
 x i=a i−r i //primul element minus rația, adesea 0=1-1
 cât timp i>0
◦ dacă i=¿ n+1 //configurație de tip soluție?
 reține soluția Sol=( x 1 , x 2 , … , x n )
 i=i−1 //revenire după construirea unei soluții
◦ altfel
 vb=0 //variabila de impas
 cât timp x i< s i și vb=¿ 0 //alegere nouă valoare x i
 x i=x i+ r i //următorul termen
 vb=posibil( x i)// verficare condiții de continuare
 dacă vb=¿ 0 //impas => revenire
 i=i−1
 altfel //avans
 i=i +1
 x i=a i−r i
 Exemple de probleme care se rezolvă prin metoda backtracking:
◦ Problema celor 8 ◦ Generarea ◦ Problema
(n) regine. tuturor permutărilor. colorării hărților.
◦ Problema ◦ Generarea
cavalerilor mesei rotunde. tuturor aranjamentelor.
◦ Plata unei sume ◦ Generarea
(cu/fără bancnotă unitate). tuturor combinărilor.

Problema celor 8 regine


X =( x 1 , x 2 , … , x 8 )
x i - coloana pe care se află regina de pe linia i
Si= {1 , 2 ,3 , 4 , 5 ,6 , 7 , 8 }
a i=1, r i=1 , si=8

Condiție de continuare
Regina plasată, i
nu e pe aceeași linie cu una plasată anterior
implicit, nu e nevoie de verificare
nu e pe aceeași coloană cu una plasată anterior
x i ≠ x j pentru j=1 ,i−1
nu e pe aceeași diagonală cu una plasată anterior
|i− j|≠|x i−x j| pentru j=1 ,i−1
Condiţie finală nu e necesară
//retine solutia - afisarea solutiei sol, a nrs-a
void retine_solutia(int nrs, int n, int *sol) //verificare indeplinire conditie de continuare
{ int posibil(int n, int k, int *x)
cout<<"Solutia "<<nrs<<"\n"; {
int i,j; int i;
for(i=0;i<n;i++){ int OK=1;
for(j=0;j<n;j++) for (i=0;i<k && OK;i++)
if(sol[i]==j) if((abs(i-k)==abs(x[i]-x[k]))||
cout<<"R "; (x[i]==x[k]))
else OK=0;
cout<<"* "; return OK;
cout<<endl; }
}}

//implementarea recursiva {
int regine_r(int nrs, int n, int i, int *x) int j;
if(i==n){
nrs++;
retine_solutia(nrs,n,x);
}
else
for(j=0;j<n;j++){
x[i]=j;
if (posibil(n,i,x))
nrs=regine_r(nrs,n,i+1,x);
}
return nrs; }
//implementare iterativa
int regine_i(int n)
{
int i,j,p,nrs;
int *x=new int[n+1];
i=0;x[0]=-1;nrs=0;
while(i>=0)
if(i==n){
nrs++;retine_solutia(nrs,n,x);i-
}
else{
p=0;
for(j=x[i]+1;j<n && !p;j++){
x[i]=j;
p=posibil(n,i,x); }
if(p){i++;x[i]=-1;}
else i--;
}
delete x; return nrs;}

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