Documente Academic
Documente Profesional
Documente Cultură
Proiect realizat de Pintilie Andreea Raluca Clasa a X a D Profesor coordonator: Iordachi Lizeta
Backtracking este numele unui algoritm general de descoperire a tuturor soluiilor unei probleme de calcul, algoritm ce se bazeaz pe construirea incremental de soluii-candidat, abandonnd fiecare candidat parial imediat ce devine clar c acesta nu are anse s devin o soluie valid.
TEHNICA BACKTRACKING
Aceast tehnic poate fi utilizat pentru rezolvarea problemelor de cutare. Cutarea efectuat este exhaustiv, putnd fi folosit pentru generarea tuturor soluiilor posibile. Tehnica Backtracking are la baz un principiu extrem de simplu: - se construiete soluia pas cu pas: x1, x2 ,xn - dac se constat c, pentru o valoare aleas, nu avem cum s ajungem la soluie, se renun la acea valoare i se reia cutarea din punctul n care am rmas. Se folosete n rezolvarea problemelor care ndeplinesc simultan urmtoarele condiii: Soluia lor poate fi pus sub forma unui vector V = x1,x2,x3, . xn, cu x1A1, . Xn An Mulimile A1, A2, An sunt mulimi finite, iar elementele lor se afl ntr-o ordine bine stabilit Nu se dispune de o metod de rezolvare mai rapid
ALGORITMUL METODEI
se alege primul element x1, ce aparine lui A1; presupunnd generate elementele x1 xk, vom avea 2 posibiliti: nu s-a gsit un astfel de element, caz n care se reia cutarea, considernd generate elementele x1 xk-1, iar aceasta se reia de la urmtorul element Ak, rmas netestat. a fost gsit, caz n care se testeaz dac acesta ndeplinete anumite condiii (rspunsul poate fi verificat de o funcie Validare care returneaz true sau false). dac le ndeplinete, se testeaz dac s-a ajuns la soluie (se utilizeaz funcia Soluie, care returneaz true dac s-a ajuns la soluie) dac s-a ajuns la soluie, se tiprete i se continu algoritmul pentru gsirea unei alte soluii, considerndu-se generate x1 xk, iar elementul xk+1 se caut printre elementele mulimii Ak+1 rmase netestate dac nu s-a ajuns la soluie se reia algoritmul considerndu-se generate elementele x1, xk, xk+1 dac nu le ndeplinete se reia algoritmul considernd generate x1xk, iar elementul xk+1 se caut printre elementele mulimii Ak+1 rmase netestate
RUTINA BACKTRACKING
k:=1; init(1,st); while k>0 do begin repeat succesor (as, st, k) ; . if as then valid(ev,st,k) until (not as) or (as and ev) ; if as then if solutie(k) then tipar else begin k:=k+l; init ( k, st ); end; else k:=k-1 end;
PROTOTIP RECURSIV
//Generarea permutarilor nivelul n
void back(int k) //incarcarea nivelului k {for(int i=1;i<=n;i++) //caut printre toate nr de la 1 la n {st[k]=i; //le incarc pe rand in stiva if(valid(k)) //daca sunt valide void tipar(int k) //afisarea solutiei if(solutie(k)) //daca am ajuns la solutie {for(int i=1;i<=k;i++) cout<<st[i]<<' '; tipar(k); cout<<endl;} else back(k+1); //daca nu am solutie, int valid(int k) //verifica daca elementul de pe inseamna ca am // o "bucatica" de solutie si urc pe nivelul k este valid urmatorul nivel in stiva { } for(int i=1;i<k;i++) //caut elementul de pe } nivelul k pe nivelele anterioare if(st[i]==st[k]) return 0; //daca il gasesc, elementul nu e valid int main() return 1;} {cin>>n; back(1);//incep incarcarea stivei cu nivelul 1 int solutie(int k) } {return k==n;}//am solutie cand am ajuns la
PROTOTIP ITERATIV
//generarea permutarilor #include<iostream> #include<math.h> using namespace std; int n,st[100]; void tipar(int n) {for(int i=1;i<=n;i++) cout<<st[i]<<' '; cout<<endl;} int valid(int k) {for(int j=1;j<k;j++) if (st[k]==st[j]) return 0; return 1;} {if (st[k]<n)//daca elementul din varf mai poate fi marit {st[k]++;//il maresc if (valid(k))//daca e valid if (k==n) //daca am ajuns la nivelul n, am solutie tipar(n);//si o tiparesc else st[++k]=0;//altfel, cresc k si resetez continutul stivei } else k--; //inseamna ca st[k]==n si cobor in stiva, pentru a mari continutul nivelului precedent } }
void back() int main() {int k=1;//plec de la nivelul 1 { st[1]=0;//initializez nivelele cu o valoare cu 1 cin>>n; mai mica decat cea mai mica valoare pe care o back(); pot avea in stiva } while (k>0)//cat timp mai sunt in stiva
PROBLEME REZOLVATE
ENUNT : Fie n numar natural nenul.Scrieti un program de generare a permutarilor de ordin n a elementelor multimii {1, 2, 3,..., n}. EXEMPLU: Pentru n=3 programul va genera 123 132 213 231 312 321
SOLUTIE: Permutarile de ordin n reprezinta toate posibilitatile de a aranja elementele unei multimi de n elemente. I. Solutia x[1]......x[n] - x[i] va avea ca valoare un element al multimii II. x[k] poate avea ca valoare orice valoare din intervalul [1,n] III. Valid - elementele trebuie sa fie distincte x[k] trebuie sa fie diferit de x[1]...x[k-1] Implementare #include<iostream> using namespace std; char sp[]=" ";
int Valid(int k) { int i; for(i=1;i<=k-1;i++) if (x[k]==x[i]) return 0; return 1; } void BackRec(int k) { int i; for(i=1;i<=n;i++) { x[k]=i; if (Valid(k)) if (k==n) Afisare(); else BackRec(k+1); } }
int x[10], n, nrsol=0; void Afisare() { int i; cout<<sp; for(i=1;i<=n;i++) cout<<x[i]<<" "; cout<<endl; nrsol++; if (nrsol%23==0) cin.get(); }
int main() { cout<<endl<<endl<<sp<<"Permutarile primelor n numere naturale (n<10)"<<endl; cout<<endl<<sp<<" Dati valoarea lui n: "; cin>>n; cout<<endl; BackRec(1); cout<<endl<<sp<<"Numar solutii: "<<nrsol; return 0; }
Implementare #include<iostream> using namespace std; char sp[]=" "; int x[20], n, nrsol=0, a[20]; void Afisare() {int i,j; cout<<sp; for(i=1;i<=n;i++) cout<<x[i]<<" "; cout<<endl; nrsol++; if (nrsol%24==0) cin.get(); } void BackRec(int k) {int i; for(i=1;i<=a[k];i++) {x[k]=i; if (k==n) Afisare(); else BackRec(k+1);
} } int main() {int i; cout<<endl<<endl<<sp<<"Produsul cartezian a n multimi de cardinal a1, a2, ... an"<<endl; cout<<endl<<sp<<" Dati valoarea lui n: "; cin>>n; cout<<endl<<sp<<" Dati cardinalul fiecarei multimi: "<<endl<<endl; for (i=1;i<=n;i++) { cout<<sp<<" Multimea "<<i<<": "; cin>>a[i]; } BackRec(1); cout<<endl<<sp<<"Numar solutii: "<<nrsol; return 0; }