Răspuns :
O soluţie are forma unui vector
Mulţimile sunt finite având elemente aflate într-o relaţie
de ordine bine stabilită
Se caută soluţia/soluţiile valide în spaţiul tuturor soluţiilor
Nu există altă rezolvare cu timp de rulare mai rapid
, ,..., / , ,..., , 1,... Sv
x1 x2 xn x1 A1 x2 A2 xn An v
A A An
, ,..., 1 2
Backtracking. Observații
Mulţimile pot fi identice
pot fi şi vectori
Numărul de elemente ale soluţiei poate fi sau
nu cunoscut; depinde de fiecare problemă
Dacă se caută o singură soluţie, algoritmul se
opreşte forţat pentru a economisi timp
Ai
/ i 1, n
xi
/ i 1, n
S
Backtracking. Analiza complexității
Produs cartezian: Se doreşte spargerea unui cifru
format din 4 cifre. Se presupune că există o funcție
care primeşte ca parametru o combinaţie de 4 cifre
şi returnează 0 (combinație incorectă) sau 1
(combinație corectă).
Generând produsul cartezian se
baleiază spaţiul tuturor soluţiilor:
Rezolvare : adunare cu 1 în baza 10
4, / 1, / {0..9}, 1,4
, ,..., / , ,..., , 1,...
1 2 3 4
( )
1 2 1 1 2 2
n A A i n S x x x x x j
S x x x x A x A x A v
i v j
not
v n n n
Sv
A A A A
(0,0,0,9)... (0,0,9,9)...
(0,0,0,0) (0,0,0,1) (0,0,0,2)...
10 100
1 2 3
S S
S S S
Backtracking. Analiza complexității
Permutări: Se doreşte generarea tuturor permutărilor de 4 elemente.
Se poate folosi produsul cartezian
Câte soluţii posibile? Câte valide?
4, / 1, / {1..4}, 1,4 1 2 3 4
( )
n A Ai
i n Sv
x x x x x j j
not
(1,1,2,1) (1,1,2,2) (1,1,2,3)...
(1,1,1,1) (1,1,1,2) (1,1,1,3) (1,1,1,4)
5 6 7
1 2 3 4
S S S
S S S S
Backtracking. Cu alte cuvinte
(Backtracking == Brute-force) ?
Se generează toţi candidaţii parţiali la “titlul” de soluţie
Candidaţii la soluţie se construiesc pe vectori
unidimensionali/bidimensionali
Generarea candidaţiilor se face în paşi succesivi (înainte şi inapoi)
După fiecare pas se poate face o validare pentru reducerea numărului
căutărilor în spaţiul soluţiilor
Când s-a ajuns la o anumită dimensiune a vectorului, se verifică dacă
candidatul parţial (vectorul) este sau nu o soluţie
Se alege soluţia/soluţiile din candidaţii parţiali după criterii impuse de
problemă
Backtracking. Permutări.
Generare permutări mulţime de 4 elemente.
proiectare algoritm generare permutări pornind de la un
exemplu
Pas 1: Se utilizează un vector v cu 4 elemente.
v[i] : elementul de pe poziţia i din permutare
v[3]=2 → elementul de pe poziţia 3 din permutare este 2
3 1 2 4
1
v:
index : 2 3 4
Backtracking. Permutări.
Pas 2: Se completeză vectorul v de la stânga la dreapta cu
valori succesive de la 1 la n. dacă s-a ajuns cu completarea până la un index k şi nu
există duplicate până la indexul respectiv, se continuă
completarea cu indexul k+1 (k<n).
dacă s-a ajuns cu completarea până la un index k şi nu
se mai poate completa (s-a ajuns la valoarea n) şi există
duplicate până la indexul respectiv, se continuă
completarea cu indexul k-1(k>0).
1
v:
k: 2 3 4
1
1
v:
k: 2 3 4
Backtracking. Permutări.
1 1
1
v:
k: 2 3 4
1 2
1
v:
k: 2 3 4
1 2 1
1
v:
k: 2 3 4
1 2 2
1
v:
k: 2 3 4
1 2 3
1
v:
k: 2 3 4
1 2 3 1
1
v:
k: 2 3 4
Backtracking. Permutări.
1 2 3 2
1
v:
k: 2 3 4
1 2 3 3
1
v:
k: 2 3 4
1 2 3 4
1
v:
k: 2 3 4
1 2 4
1
v:
k: 2 3 4
1 2 4 1
1
v:
k: 2 3 4
... 1 2 4 3
1
v:
k: 2 3 4
SOL
SOL
Backtracking. Permutări.
1 2 4 4
1
v:
k: 2 3 4
1 3
1
v:
k: 2 3 4
1 3 1
1
v:
k: 2 3 4
1 3 2
1
v:
k: 2 3 4
1 3 2 1
1
v:
k: 2 3 4
... 1 3 2 4
1
v:
k: 2 3 4
SOL
Backtracking. Permutări.
Pas 3: Se aleg soluţiile dintre candidaţi. Condiţia este ca toate
elementele vectorului să fie completate şi diferite între ele.
Pas 4: Se repetă algoritmul până când nu se mai îndeplineşte
condiţia: indexul k al vectorului >0 (stiva este goală).
4 3 4
1
v:
k: 2 3 4
4 4
1
v:
k: 2 3 4
4
1
v:
k: 2 3 4
1
v:
k: 2 3 4
Backtracking. Preambul implementare
Pentru generarea tuturor soluţiilor se foloseşte o structură de date de tip
stivă, v. Vârful stivei se notează cu k
Algoritmul ciclează, adăugând/modificând/ştergând valori din vârful stivei
iniţializează valoare element din vârful stivei – funcţia Init(k)
modificare valoare element din vârful stivei – funcţia Successor(k)
validarea elementului din vârful stivei – funcţia Valid(k)
dacă elementul din vârful stivei este valid, putem avea un cantidat la soluţie
- funcţia Solution(k), iar în caz favorabil, afişare - Print(k)
3 variante de poziţionare în stivă :
Nu se modifică poziţia – k rămâne neschimbat
Se urmăreşte adăugarea unui nou element în stivă – k++
Se coboară o poziţie în stivă pentru că elementul curent din vârf nu mai
satisface condiţiile problemei– k--
Backtracking. Implementare
Funcția Init
void Init(int k){ // k – vârful stivei
v[k]=0; //iniţializează/resetează, valoarea din
// vârful stivei