Sunteți pe pagina 1din 13

METODA BACKTRACKING (cutare cu revenire)

1. NECESITATE Deseori n practic trebuie s rezolvm probleme care au un numr foarte mare de soluii posibile. De cele mai multe ori ns, nu ne intereseaz toate soluiile, ci numai o parte dintre ele, care ndeplinesc anumite condiii specifice problemei. Pentru astfel de probleme este indicat folosirea metodei backtracking care evit generarea soluilor inutile. Desigur c o persoan cu o gndire simplist ar putea spune : generm toate soluiile, apoi le alegem pe cele care ndeplinesc condiiile cerute. Foarte simplu, dar... oare i eficient ? Ce rost ar avea s se genereze nite soluii care oricum nu convin? Din punctul de vedere al timpului necesar calculatorului pentru a obine toate soluiile, ct de realist este o astfel de abordare? 2. APLICABILITATE

rezolvare a problemei respective. 3. DESCRIERE

a. Se aplic n cadrul problemelor a cror soluie este de tip vector. b. Deoarece are un timp de execuie exponenial, se aplic numai atunci cnd nu exist o alt cale de

- Metoda utilizeaz structura de tip stiv i poate fi programat att iterativ ct i recursiv. Stiva este acea form de organizare a datelor (structur de date) cu proprietatea c operaiile de introducere i scoatere a datelor se fac n vrful ei. Stivele se pot simula utiliznd vectori. Prima idee pe care trebuie s o reinem ar fi: nu se genereaz toate soluiile posibile, ci numai acelea care ndeplinesc anumite condiii specifice problemei, numite condiii de validare (n unele lucrrii de specialitate acestea mai sunt numite i condiii interne).

Varianta iterativ a metodei backtracking Forma soluiei:

X = (x1 , x 2 ,...x n ) S

S = S1 xS 2 x...xS n ) card ( S ) = s i i - x 1 , x 2 , x n pot fi la rndul lor vectori, - S1 , S 2 , S n pot coincide.

Componentele vectorului X satisfac anumite relaii, numite condiii interne. Exemplu: Fie:

S1 = {a, b, c} S 2 = {m, n} condiii interne

( x1 , x 2 ) = ?

x S1 cu 1 cu proprietatea c : x2 S 2

dac x1 = a sau x1 = b x 2 n

Soluiile din spaiul soluiilor posibile S, care satisfac condiiile interne, se numesc soluii rezultat. (a,m), (b,m), (c,m), (c,n) Construirea soluiei: 1) P.p. c x1, ,xk-1 au primit valori i satisfac condiiile de continuare 2) Atribuim o valoare lui xk Sk 3) Verificm condiiile de continuare referitoare la x1,x2, ,xk - dac sunt ndeplinite condiiile de continuare atunci se trece la atribuirea unei xk+1 Sk+1 - dac nu sunt ndeplinite condiiile de continuare: - oricum vom alege xk+1, , xn nu se va ajunge la o soluie rezultat - se va face o nou alegere pentru xk Sk - dac Sk s-a epuizat k=k-1 i se face o nou alegere pentru xk-1 Sk-1 Obs: 1. Condiiile de continuare trebuie s fie necesare i suficiente pentru obinerea unui rezultat 2. Cnd k=n condiiile interne = condiii de continuare (se refer la vectorul soluie) 3. Condiia k=n+1 este utilizat pentru a sesiza obinerea unei soluii 4. Condiia k=0 este utilizat pentru a sesiza sfritul procesului de construire a soluiilor

valori pentru

... xk

st

x2 x1
Aplicaii 1. Utiliznd metoda backtracking se genereaz n ordine lexicografic cuvintele de cte patru litere din mulimea A={a,b,c,d,e}, cuvinte care nu conin dou vocale alturate. Primele opt cuvinte generate sunt, n ordine: abab, abac, abad, abba, abbb, abbc, abbd, abbe. Cte dintre cuvintele generate ncep cu litera b i se termin cu litera e? a. 9 b. 15 c. 12 d. 20

2. Utiliznd metoda backtracking se genereaz n ordine lexicografic cuvintele de cte patru litere din mulimea A={a,b,c,d,e}, cuvinte care nu conin dou vocale alturate. Primele opt cuvinte generate sunt, n ordine: abab, abac, abad, abba, abbb, abbc, abbd, abbe. Care este ultimul cuvnt generat? a. edcb b. eeee c. edde d. eded

3. Utiliznd metoda backtracking se genereaz n ordine lexicografic cuvintele de cte patru litere din mulimea A={a,b,c,d,e}, cuvinte care nu conin dou vocale alturate. Primele opt cuvinte generate sunt, n ordine: abab, abac, abad, abba, abbb, abbc, abbd, abbe.

Care este penultimul cuvnt generat? a. edec b. eded c. edde d. edcb

4. Utiliznd metoda backtracking se genereaz n ordine lexicografic cuvintele de cte patru litere din mulimea A={a,b,c,d,e}, cuvinte care nu conin dou vocale alturate. Primele opt cuvinte generate sunt, n ordine: abab, abac, abad, abba, abbb, abbc, abbd, abbe. Care este antepenultimul cuvnt generat? a. edde b. eddb c. edeb d. edcb

5. Folosind modelul combinrilor se genereaz numerele naturale cu cte trei cifre distincte din mulimea {1,2,3,7}, numere cu cifrele n ordine strict cresctoare, obinndu-se, n ordine: 123, 127, 137, 237. Dac se utilizeaz exact aceeai metod pentru a genera numerele naturale cu patru cifre distincte din mulimea {1,2,3,4,5,6,7,8}, cte dintre numerele generate au prima cifr 2 i ultima cifr 7? a. 8 b. 3 c. 4 d. 6

6. Utiliznd metoda backtracking sunt generate numerele de 3 cifre, avnd toate cifrele distincte i cu proprietatea c cifrele aflate pe poziii consecutive sunt de paritate diferit. tiind c primele ase soluii generate sunt, n aceast ordine, 103, 105, 107, 109, 123, 125, care este a zecea soluie generat? a. 145 b. 147 c. 230 d. 149 7. Folosind tehnica bactracking un elev a scris un program care genereaz toate numerele de cte n cifre (0<n9), cifrele fiind n ordine strict cresctoare. Dac n este egal cu 5, scriei n ordine cresctoare toate numerele avnd cifra unitilor 6, care vor fi generate de program. C95 =126 numere 8. Utiliznd metoda backtracking sunt generate numerele de 3 cifre care au cifrele n ordine cresctoare, iar cifrele aflate pe poziii consecutive sunt de paritate diferit. tiind c primele cinci soluii generate sunt, n aceast ordine, 123, 125, 127, 129, 145, care este cel de al 8-lea numr generat? a. 169 b. 149 c. 167 d. 147 9. Utiliznd metoda backtracking, sunt generate n ordine cresctoare toate numerele de 3 cifre, astfel nct cifrele sunt n ordine cresctoare, iar cifrele aflate pe poziii consecutive sunt de paritate diferit. tiind c primele trei soluii generate sunt, n aceast ordine, 123, 125, 127, scriei toate numerele generate care au suma cifrelor egal cu 12. 1 10. Un algoritm de tip backtracking genereaz, n ordine lexicografic, toate irurile de 5 cifre 0 i 1 cu proprietatea c nu exist mai mult de dou cifre 0 pe poziii consecutive. Primele 7 soluii generate sunt: 00100, 00101, 00110, 00111, 01001, 01010, 01011. Care este a 8-a soluie generat de acest algoritm? a. 01110 b. 01100 c. 01011 d. 01101

11. Utiliznd metoda backtracking se genereaz permutrile cuvntului info. Dac primele trei soluii generate sunt: fino, fion, fnio care este cea de-a cincea soluie? (4p.) a. foin b. fnoi c. foni d. ifon 12. Cte numere cu exact dou cifre pot fi construite folosind doar cifre pare distincte? (4p.) a. 12 b. 16 c. 20 d. 25

13. Un algoritm genereaz n ordine cresctoare toate numerele de n cifre, folosind doar cifrele 3, 5 i 7. Dac pentru n=5, primele cinci soluii generate sunt 33333, 33335, 33337,

33353, 33355, precizai care sunt ultimele trei soluii generate, n ordinea generrii. (7,7,7,7,3) (7,7,7,7,5) (7,7,7,7,7) 14. Un algoritm genereaz n ordine descresctoare toate numerele de 5 cifre, fiecare dintre ele avnd cifrele n ordine strict cresctoare. tiind c primele cinci soluii generate sunt 56789, 46789, 45789, 45689, 45679, precizai care sunt ultimele trei soluii generate, n ordinea generrii. 12347, 12346, 12345 18 Algoritm n pseudocod (soluii cu acelai numr de componente = n) k=1; st[k]=0; // iniializare stiv while (k>0) if (k= =n+1) // configuraia e de tip soluie tipar(); k--; else if (exist valori neconsumate n Sk) {se atribuie o valoare pentru xk Sk! if (valid(k)) // valoarea aleas satisface condiiile de continuare { k++; st[k]=0; } } else {st[k]=0; k--; } Aplicaii Generarea permutrilor mulimii {1, 2, , n} Exp: {1, 2, 3} X=(x1,x2.x3) S={1, 2, 3}x{1, 2, 3}x{1, 2, 3} Nr. sol: 3! = 6 123 132 213 231 312 321 Condiii interne: st[i]!=st[k] #include<iostream.h> int st[10],k,n,nrsol=0; void init() {for (i=1;i<=p;i++)

i k

st[i]=0;

void tipar() {for (int i=1;i<=n;i++) cout<<st[i]<< ; } int valid(int k) { for (int i=1;i<k;i++) if (st[i]==st[k]) return 1; }

return 0;

void back() {k=1; while (k>0) if (k==n+1) {nrsol++; cout<<"Solutia cu nr: "<<nrsol<<endl; tipar(); cout<<endl; k--; } else if (st[k]<n) {st[k]++; if (valid(k)) k++; } else {st[k]=0; k--; } } void main() {cout<<"n="; cin>>n; back(); cout<<endl; cout<<"nrsol="<<nrsol; } Generarea aranjamentelor Anp

Anp =
Exp: {1,2,3}

n! (n p )!
p=2

A32 =
1,2 1,3 2,1 2,3 3,1 3,2

3! =6 1!

Dim. sol: p Condiii interne: st[i]!=st[k]

i k

#include<iostream.h> int st[10],n,i,k, nrsol=0, p; void init() {for (i=1;i<=p;i++) st[i]=0; } void tipar() {for (i=1;i<=p;i++) cout<<st[i]<<" "; cout<<endl; } int valid (int k) { for (i=1;i<k;i++) if (st[i]==st[k]) return 0; } return 1;

void back() { k=1; while (k>0) if (k==p+1) {nrsol++; cout<<"Solutia cu nr. "<<nrsol<<" este:"<<endl; tipar(); k--; } else if (st[k]<n) {st[k]++; if (valid(k)) k++; } else {st[k]=0; k--; } } void main() {cout<<"n="; cin>>n; cout<<"p=";cin>>p; init(); back(); cout<<endl; cout<<"Nr. sol ="<<nrsol<<endl; } Generarea combinrilor Cnk

C np =
Exp:

n! (n p )! p!

{1,2,3}

p=2

C 32 =
1,2 1,3 2,3

3! =3 1!2!

Dim. sol: p Condiii interne: st[k]>st[k-1] k > 1 #include<iostream.h> int st[10],n,i,k,nrsol=0,p; void init() {for (i=1;i<=p;i++) st[i]=0; } void tipar() {for (i=1;i<=p;i++) cout<<st[i]<<" "; cout<<endl; } int valid (int k) { if (k==1) return 1; if (st[k]>st[k-1]) return 1; else return 0; } void back() { k=1; while (k>0) if (k==p+1) {nrsol++; cout<<"Solutia cu nr. "<<nrsol<<" este:"<<endl; tipar(); k--; } else if (st[k]<n) {st[k]++; if (valid(k)) k++; } else {st[k]=0; k--; }

} void main() {cout<<"n="; cin>>n; cout<<"p=";cin>>p; init(); back(); cout<<endl; cout<<"Nr. sol ="<<nrsol<<endl; } Problema celor n dame pe o tabl de ah Fiind dat o tabl de ah, de dimensiune n, xn, se cer toate soluiile de aranjare a n dame, astfel nct s nu se afle dou dame pe aceeai linie, coloan sau diagonal (dame s nu se atace reciproc). Exemplu: Presupunnd c dispunem de o tabl de dimensiune 4x4, o soluie ar fi urmtoarea: D D D D Observm c o dam trebuie s fie plasat singur pe linie. Plasm prima dam pe linia 1, coloana 1. D

A doua dam nu poate fi aezat dect n coloana 3. D D

Observm c a treia dam nu poate fi plasat n linia 3. ncercm atunci plasarea celei de-a doua dame n coloana 4. D D

A treia dam nu poate fi plasat dect n coloana 2. D D D

n aceast situaie dama a patra nu mai poate fi aezat.

ncercnd s avansm cu dama a treia, observm c nu este posibil s o plasm nici n coloana 3, nici n coloana 4, deci o vom scoate de pe tabl. Dama a doua nu mai poate avansa, deci i ea este scoas de pe tabl. Avansm cu prima dam n coloana 2. D

A doua dam nu poate fi aezat dect n coloana 4. D D

Dama a treia se aeaz n prima coloan. D D D

Acum este posibil s plasm a patra dam n coloana 3 si astfel am obinut o soluie a problemei. D D D D Algoritmul continu n acest mod pn cnd trebuie scoas de pe tabl prima dam. Pentru reprezentarea unei soluii putem folosi un vector cu n componente (avnd n vedere c pe fiecare linie se gsete o singur dam). Exemplu pentru soluia gsit avem vectorul ST ce poate fi asimilat unei stive. Dou dame se gsesc pe aceeai diagonal dac si numai dac este ndeplinit condiia: |st(i)-st(j)|=|i-j| ( diferena, n modul, ntre linii si coloane este aceeai). ST(4)

3 1 4 2

ST(3) n general ST(i)=k semnific faptul c pe linia i dama ocup poziia k. ST(1)

ST(2)

Exemplu: n tabla 4 x4 avem situaia: st(1)= 1 i = 1 D st(3)= 3 j = 3 D |st(1) - st(3)| = |1 3| = 2 |i j| = |1 3| = 2 D sau situaia

D D D D

st(1) = 3 i = 1 st(3) = 1 j = 3 |st(i) - st(j)| = |3 1| = 2 |i j| = |1 3| = 2

ntruct doua dame nu se pot gsi n aceeai coloan, rezult c o soluie este sub form de permutare. O prim idee ne conduce la generarea tuturor permutrilor si la extragerea soluiilor pentru problema ca dou dame s nu fie plasate n aceeai diagonal. A proceda astfel, nseamn c lucrm conform strategiei backtracking. Aceasta presupune ca imediat ce am gsit dou dame care se atac, s relum cutarea. lat algoritmul, conform strategiei generate de backtracking: - n prima poziie a stivei se ncarc valoarea 1, cu semnificaia c n linia unu se aeaz prima dam n coloan. - Linia 2 se ncearc aezarea damei n coloana 1, acest lucru nefiind posibil ntruct avem doua dame pe aceeai coloan. - n linia 2 se ncearc aezarea damei n coloana 2 , ns acest lucru nu este posibil, pentru c damele se gsesc pe aceiai diagonal (|st(1)-st(2)|=|1-2|); - Aezarea damei 2 n coloana 3 este posibil. - Nu se poate plasa dama 3 n coloana 1, ntruct n liniile 1-3 damele ocupa acelai coloan. - i aceast ncercare eueaz ntruct damele de pe 2 i 3 sunt pe aceeai diagonal. - Damele de pe 2-3 se gsesc pe aceeai coloan. - Damele de pe 2-3 se gsesc pe aceeai diagonal. - Am cobort n stiv mutnd dama de pe linia 2 i coloana 3 n coloana 4. Algoritmul se ncheie atunci cnd stiva este vid.

Conditii interne:

st[i ] {1,2,..., n} st[i ] st[ j ], i j , i, j = 1, n


Damele nu pot fi plasate pe aceeasi coloana Damele nu pot fi plasate pe aceeasi diagonala

i j st[i ] st[ j ] , i j , i, j = 1, n

#include<iostream.h> #include<math.h> int st[10],n,i,k,nrsol=0,j; void init() {for (i=1;i<=n;i++) st[i]=0; } void tipar() {for (i=1;i<=n;i++) {for (j=1;j<=n;j++) if (st[i]==j) cout<<" R "; else cout<<" * "; cout<<endl; } }

int valid (int k) { for (i=1;i<k;i++) if (st[i]==st[k] || abs(i-k)==abs(st[i]-st[k])) return 0; return 1; } void back() { k=1; while (k>0) if (k==n+1) {nrsol++; cout<<"Solutia cu nr. "<<nrsol<<" este:"<<endl; tipar(); k--; } else if (st[k]<n) {st[k]++; if (valid(k)) k++; } else {st[k]=0; k--; } } void main() {cout<<"n="; cin>>n; init(); back(); cout<<endl; cout<<"Nr. sol ="<<nrsol<<endl; }

BACKTRACKING IN PLAN Problemele n plan necesit parcurgerea unui tablou unidimensional, iar cele mai cunoscute sunt: parcurgerea tablei de ah cu un cal, fr a trece de dou ori prin aceeai poziie gsirea ieirii dintr-un labirint Problemele care se rezolv prin metoda backtracking n plan au ca cerin deplasarea n tablou, pe linii, coloane sau diagonale sau prin sritur (de obicei sritura calului) dintr-un punct n alt punct al tabloului sau pe frontier (prima linie sau coloan, ultima linie sau coloan) eventual respectnd anumite condiii de deplasare. Dac ne gsim ntr-un anumit punct iar cerina este de a ne deplasa n unul din cei opt vecini ai lui vom utiliza pentru acest lucru dou cicluri for de la 1 la 1 cu care valori vom modifica coordonata punctului curent. Dac deplasarea este permis numai pe linii condiia de respectat este ca suma n valoare absolut pentru cei doi indici s fie 1, iar pentru deplasarea pe diagonal 2. De asemenea se mai impune condiia de a nu prsi tabloul, lucru care l vom respecta testnd coordonatele noului punct s aparin mulimii [1..nrlinii] i [1..nrcol]. Sritura calului. Fiind dat o tabl de ah de dimensiunea nxn i un cal n colul stnga sus al acesteia, se cere s se afieze toate posibilitile de mutare a acestei piese de ah astfel nct s treac o singur dat prin fiecare ptrat al tablei. O soluie va fi afiat ca o matrice nxn n care sunt numerotate sriturile calului.

Exemplu, pentru n=5, o soluie este 1 14 9 20 23 10 19 22 15 8 5 2 13 24 21 18 11 4 7 16 3 6 17 12 25 Pentru rezolvarea acestei probleme vom codifica direciile de deplasare pentru c ar fi ineficient s scriem dou cicluri for de la 2 la 2 cu cele 25 de variante de deplasare din care valide sunt doar opt. De asemenea aici spre deosebire de celelalte probleme tratate la aplicarea metodei backtracking n plan nu vom folosi un vector soluie, ci vom scrie sriturile n tablou urmrind ca la revenire s refacem poziiile ocupate pentru a nu se lua blocaje. n figura de mai jos sunt prezentate cele 8 mutri posibile pentru un cal.

PH

#include<fstream> #include<iostream> using namespace std; const int dx[8]={-1,1,2,2,1,-1,-2,-2}; const int dy[8]={-2,-2,-1,1,2,2,1,-1}; int a[10][10],n; ofstream f("cal.out"); void afis() { int i,j; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) f<<a[i][j]<<" "; f<<endl; } f<<endl; } int inside(int i,int j) { return (i>=1 && i<=n && j>=1 && j<=n); } void back(int i, int j, int pas) { int k,inou,jnou; a[i][j]=pas; if (pas==n*n) afis(); else for(k=0;k<8;k++) { inou=i+dx[k]; jnou=j+dy[k]; if (inside(inou,jnou) && a[inou][jnou]==0) back(inou,jnou,pas+1); } a[i][j]=0; } int main() { cin>>n; back(1,1,1); f.close(); return 0; }

13

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