Vous êtes sur la page 1sur 13

Metoda BACKTRACKING

La dispoziţia celor care rezolvă probleme cu ajutorul calculatorului există


mai multe metode . Dintre acestea cel mai des utilizate sunt:

- metoda Greedy;
- metoda Divide et impera;
- metoda Backtracking;

Metoda Backtracking se aplică problemelor în care soluţia poate fi


reprezentată sub forma unui vector – x = (x1, x2, x3, …xk,… xn) € S, unde
S este mulţimea soluţiilor problemei şi S = S1 x S2 x… x Sn, şi Si sunt
mulţimi finite având s elemente si xi € si , (¥)i = 1..n.

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 v
a 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.

Metoda se aplica astfel :


1) se alege prima valoare sin S1 si I se atribuie lui x1 ;
2) se presupun generate elementele x1…x[k-1], cu valori din S1..S[k-1];
pentru generarea lui x[k] se alege primul element din S[k] disponibil
si pentru valoarea aleasa se testează îndeplinirea condiţiilor de
continuare.

3
Pot apărea următoarele situaţii :
a) x[k] îndeplineşte condiţiile de continuare. Daca s-a ajuns la
soluţia finală (k = n) atunci se afişează soluţia obţinută. Daca nu
s-a ajuns la soluţia finală se trece la generarea elementului
următor – x [k-1];
b) x[k] nu îndeplineşte condiţiile de continuare. Se încearcă
următoarea valoare disponibila din S[k]. Daca nu se găseşte nici
o valoare în S[k] 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 lui S1.

Este o tehnica de programare aplicabila algoritmilor care oferă mai multe soluţii şi
are ca rezultat obţinerea tuturor soluţiilor problemei. Fiecare soluţie se memorează într-o
structura de date de tip stivă implementată cu ajutorul unui vector. Deci fiecare soluţie
poate fi pusă sub forma unui vector.

Într-un algoritm backtracking ne interesează toate soluţiile posibile. Pentru a obţine


fiecare soluţie finală se completează stiva nivel cu nivel trecând astfel prin nişte soluţii
parţiale. Astfel soluţiile finale cât şi cele parţiale pentru a fi luate în considerare trebuie să
îndeplinească anumite condiţii numite condiţii de validare. O soluţie care îndeplineşte o
astfel de condiţie se numeşte soluţie validă.
Toate configuraţiile stivei ce reprezintă soluţii finale sunt alcătuite din elementele
aceleiaşi mulţimi bine definite pe care o numim mulţimea soluţiilor. Fiecare nouă soluţie
parţială se obţine prin completarea soluţiei parţiale precedente cu încă o nivel pe stivă. La
fiecare nivel se pun valori din mulţimea soluţiilor care nu au fost încercate până când se
obţine o soluţie validă. În acest moment se trece la nivelul următor în stivă pentru a
completa mai departe soluţia reluând încercările pe noul nivel.

La un moment dat pe un anumit nivel nu mai există nici o valoare


neîncercată din mulţimea valorilor problemei. În acest caz se face un pas înapoi în stivă la
nivelul anterior şi se reia căutarea cu valorile rămase neîncercate pe acest nivel anterior.

Respectivul nivel a mai fost vizitat dar l-am abandonat după ce am pus
o valoare care a generat o soluţie validă. Deci este posibil să fi rămas aici valori
neîncercate. Dacă nici pe acest nivel nu mai avem valori neîncercate mai facem un pas
înapoi în stivă. Mecanismul revenirilor a determinat denumirea de metoda backtracking.

4
Plecând de la nivelul 1 şi repetând algoritmul până când pe toate
nivelele au fost încercate toate valorile din mulţimea valorilor se obţin soluţii finale care se
tipăresc.

Vom implementa metoda backtracking iterativ folosind o rutină unică


aplicabilă oricărei probleme. Rutina va apela proceduri şi funcţii care au întotdeauna
acelaşi nume şi parametri şi care din punct de vedere al metodei realizează acelaşi lucru.

Algoritmul metodei Backtracking:

1) Varianta iterativă

Algoritm generare
start
k1
x[k]1
cât timp (k>0) execută
sem0
cât timp (in mulţimea Mk mai sunt valori netestate pentru xk) şi (sem=0)
executa
x[k]x[k]+1
dacă (x[k] are o valoare validă) atunci sem1
sfârşit dacă
sfârşit cât timp
dacă (sem=1) atunci
dacă (k=n) atunci
tipăreşte
altfel
kk+1
x[k]valoare iniţiala;
sfârşit dacă
altfel
kk-1
sfârşit dacă
sfârşit cât timp
stop

5
Descrierea algoritmului iterative

Pe prima poziţie din tabloul soluţie X (k=1) se pune o valoare iniţiala. In cazul
general, aceasta valoare este minima admisibila pe care o poate lua primul element
x[1] din mulţimea de valori M1 din care se scade o unitate.
Iniţializarea unui element xk se face astfel pentru ca la prima incrementare a
acestuia să i se atribuie prima valoare din mulţimea Mk de valori.
Variabila k păstrează poziţia curentă din tabloul X în care se va depune noul
element.
Variabila sem are rolul de a semnala situaţia în care elementul xk respecta
condiţiile interne. Se căuta în mulţimea Mk de valori (prin
incrementarea valorii curente a elementului xk : X[k] :=X[k]+1) prima valoare care
respecta condiţiile interne. Aceasta valoare xk, se compara cu elementele depuse in
tablou pentru a se verifica condiţiile de validare (valid(xk)). Daca valoare este valida
atunci sem1.
Dacă valoarea găsita pentru xk poate participa la generarea soluţiei, atunci se
verifică dacă s-au completat cu valori toate elementele din soluţie ; dacă s-a generat
o soluţie, aceasta este tipărita ; astfel, se trece la următorul element candidat la
generarea soluţiei (kk+ 1) ; x[k+1] este iniţializat cu o valoare corespunzătoare şi
sunt reluate verificările precedente.
Dacă in mulţimea Mk nu mai exista valori pe care sa le poate lua xk sem
rămâne 0 şi se caută o noua valoare pentru elementul xk-1.
Generarea soluţiilor are loc cat timp pentru primul element al tabloului soluţie
mai există valori în mulţimea M1 de valori. Dacă nu mai există astfel de valori,
poziţia curenta k, în tablou devine zero şi algoritmul se opreşte.

6
2) Varianta recursivă

Algoritm generare(k)
Start
pentru i valoare iniţiala, valoare maxima admisibilă din Mk execută
x[k]i
dacă (x[k] are o valoare validă) atunci
dacă(k=n) atunci tipăreşte
altfel generare (k+1)
sfârşit dacă
sfârşit dacă
sfârşit pentru
Stop.

Descrierea algoritmului recursiv

Se pune pe prima poziţie din tabloul soluţie (k=1, generare(1)) o valoare


iniţială (x[1]i).
Variabila k păstrează poziţia curenta din tabloul X in care se va depune un nou
element.

Se caută in mulţimea Mk de valori prima valoare(prin incrementarea valorii


curente a elementului xk, X[k]=X[k]+1) care respecta condiţiile interne. Aceasta
valoare xk se compara cu elementele depuse in tablou pentru a se verifica condiţiile
de validare(valid(xk)).

Dacă valoarea găsita pentru xk poate participa la generarea soluţiei, atunci se


verifica daca s-au completat cu valori toate elementele din soluţie; dacă s-a generat
o soluţie, aceasta este tipărita; astfel se trece la următorul element candidat la
generarea soluţiei prin autoapelul algoritmului(generare(k+1)). Prin autoapel se trece
la un nou element din tabloul soluţie X(se urca in stiva).

Daca in mulţimea Mk nu mai exista valori sa le poată prelua xk se caută o noua


valoare pentru elementul xk-1(kk-1).Aceasta trecere la elementul xk-1 se face pe
baza mecanismului recursivităţii la revenirea dintr-o instanţa a subprogramului

7
recursiv (prin extragerea din vârful stivei a fiecărei valori depuse, se coboară in
stiva).

Generarea soluţiilor are loc cat timp, pentru primul element al tabloului
soluţie, mai exista valori in mulţimea M1. Daca nu mai exista astfel de valori, poziţia
curenta k, in tablou, devine zero si algoritmul de generare se opreşte.

Observaţii:

Problemele rezolvate prin această metodă necesită un timp


îndelungat de execuţie. Din acest motiv este bine să utilizăm metoda
atunci numai atunci când nu mai avem la dispoziţie un alt algoritm mai
eficient

Nu există probleme pentru care nu se cunosc algoritmi eficienţi de


rezolvare, deci backtracking este indicată.

Rezolvarea iterativă încalcă principiul stivei atunci când


verificăm condiţiile de continuare, sau atunci când tipărim soluţia
găsită, pentru că accesăm orice nivel al stivei. Consider că o structură
trebuie folosită ca atare atunci când este strict necesar. De exemplu,
chiar şi segmentul de stivă al calculatorului poate fi accesat oriunde.
Asta nu înseamnă că acolo nu se utilizează din plin „mecanismul” stivei.

8
Problema comis-voiajorului

Enunţ:
Un comis voiajor trebuie să viziteze un număr n de oraşe.
Iniţial, el se află într-unul dintre ele, notat 1. Comis – voiajorul
doreşte să nu treacă de două ori prin acelaşi oraş, iar la întoarcere
să revină în oraşul 1. Cunoscând legăturile existente între oraşe, se
cere să se tipărească toate drumurile posibile pe care le poate
efectua comis – voiajorul.

Rezolvare in pseudocod:

procedura tipar
j nr natural
pentru j <- 1,n executa
scrie a[j]

procedura back (k nr întreg)


i,t,cont nr întregi
daca k=n+1
atunci tipar

altfel
pentru i <- 1,n executa
a[k] <- i
cont <-1
daca k>1
pentru t <-1,k-1
daca a[k]=a[t]
atunci cont <- 0

9
daca a[m[k-1][k]] =0
atunci cont <- 0

daca a[m[n][1]]=0
atunci cont <- 0

daca cont=1
atunci back(k+1)

start
citeşte n (n nr natural)
pentru b<-1,n (b nr natural)
pentru c<- 1,n (c nr natural)
scrie m[b][c] (valori naturale)
back(1).

Rezolvare Pascal:

program comisv;
type stiva=array[1..100] of integer;
var st:stiva;
i,j,n,k:integer;
as,ev:boolean;
a:array[1..20,1..20] of integer;

procedure init(k:integer;var st:stiva);


begin
st[k]:=1;
end;

procedure succesor(var as:boolean;var st:stiva;k:integer);


begin
if st[k]<n then begin
st[k]:=st[k]+1;
as:=true
end
else as:=false

10
end;

procedure valid(var ev:boolean;st:stiva;k:integer);


var i:integer;
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(k:integer):boolean;
begin
solutie:=(k=n)
end;

procedure tipar;
var i:integer;
begin
for i:=1 to n do
write('nodul=',st[i]);
writeln('------');
end;

begin
write('nr. de noduri=');readln(n);
for i:= 1 to n do
for j:=1 to i-1 do begin
write('a[',i,',',j,']='); readln(a[i,j]);
a[j,i]:=a[j,i];
end;
end;
st[1]:=1; k:=2;
init(k,st);
while k>0 do
begin
repeat
succesor(as,st,k);
if as then valid(ev,st,k);

11
until (not as) or (as and ev);
if as then if solutie(k) then tipar
else begin
k:=k+1;
init(k,st);
end
else k:=k-1;
end;
end.

Exemplu: În figura alăturată sunt simbolizate cele 6 oraşe, precum şi


drumurile existente între ele.

2 3

1 4

6 5

Comis – voiajorul are următoarele posibilităţi de parcurgere:


1, 2, 3, 4, 5, 6, 1;
1, 2, 5, 4, 3, 6, 1;
1, 6, 3, 4, 5, 2, 1;
1, 6, 5, 4, 3, 2, 1;

Legăturile existente între oraşe sunt date în matricea An,n. Elementele


matricei A pot fi 0 sau 1 (matricea este binară).

1, dacă există drum între oraşele i şi j;

12
A(i,j) =
0, altfel

Se observă că A(i,j) = A(j,i), oricare ar fi i,j ∈{1, 2, 3, …, n} –


matricea este simetrică.

Pentru rezolvarea problemei folosim stiva st. la baza stivei (nivelul 1)


se încarcă numărul 1. Prezentăm în continuare modul de rezolvare a
problemei.

2
De la oraşul 1 la oraşul 2 există drum, deci se va urca în stivă;
1

2
2 Oraşul 2 se mai găseşte în stivă, deci nu este acceptat;
1

3
De la oraşul 2 la oraşul 3 se găseşte drum; prin oraşul 3 nu s-a mai
2
trecut, deci oraşul 3 este acceptat.
1

Algoritmul continuă în acest mod până se ajunge din nou la nivelul 1,


caz în care algoritmul se încheie.

Un succesor, între 2 şi n, aflat pe nivelul k al stivei, este considerat


valid dacă sunt îndeplinite următoarele condiţii:
• nu s-a mai trecut prin oraşul simbolizat de succesor, deci acesta nu
se regăseşte în stivă;
• există drum între oraşul aflat la nivelul k-1 şi cel aflat la nivelul k;
• dacă succesorul se găseşte la nivelul n, să existe drum de la el la
oraşul 1.

13
BILBIOGRAFIE

1.Informatică – Manual pentru clasa a XI-a( Mioara Gheorghe, Monica


Tătărâm, Corina Achinca, Constanţa Năstase – Ed. Corint 2007)

2. Informatică – Manual pentru clasa a XI-a (Vlad Hutanu şi Tudor Sorin


– Ed L&S Soft, 2007)

3. Limbajul Pascal & Tehnici de programare – teorie si aplicaţii (ed. Else


2002).

4. Metoda backtracking cu exemple in limbajul Pascal ( Tiberiu Socaciu –


Ed. EduSoft – 2005).

5. Metode de programare, Structuri dinamice de date si Grafuri, teorie şi


aplicaţii: varianta Pascal (Eugen Popescu, Sofia Vitelaru, Mihaela
Codres, Daniel Codres, Mihaela Grindeanu, Marius Nicoli, Ecaterina
Boarnă – Ed. Else 2007)

14
CUPRINS

METODA BACKTRACKING …………………………………………3


Algoritmul metodei backtracking iterativ ..………………………5
Algoritmul metodei backtracking recursiv………………………..6
PROBLEMA COMIS-VOIAJORULUI ………………………………..8
Rezolvare pseudocod ……………………………………………..8
Rezolvare in limbajul Turbo Pascal ………………………………9
Exemplu ………………………………………………………….11
OBSERVAŢII METODA BACKTRACKING ………………………..13
BIBLIOGRAFIE..………………………………………………………14

15

Vous aimerez peut-être aussi