Sei sulla pagina 1di 24

Backtracking generare permutari si combinari Etichete : aranjamente, backtracking, backtracking in plang, combinari, generare aranjamente, generare combinari, generare

e permutari DefCamp 2011 @Iasi - conferinta regionala de hacking & INFOSEC

Cu totii stim ca Backtracking este una din cele mai cunoscute tehnici de programare. Ideea din spatele acestui algoritm este de a genera toate solutiile posibile si a le abandona in cazul in care observa ca nu indeplinesc conditiile necesare. Datorita generarii tuturor solutiilor, complexitatea algoritmului este foarte mare, dar duce sigur la generarea tuturor posibilitatilor valide. Din aceasta cauza, e o tehnica foarte cunoscuta in randul programatorilor (in special a celor care participa la concursuri si olimpiade de informatica) deoarece este considerata solutia ce trebuie abordata in cazul in care nu ai nici o idee. Structura unei functii backtracking void back(int k) { if(reject_sol(k)) return; if(accept_sol(k)) show_sol(k); for(i=0;i<n;i++) { v[k]=set(); back(k+1); v[k]=unset(); } } Generarea tuturor permutarilor Problema : Sa se genereze toate permutarile multimii {1, 2, N}, in ordine lexicografica. Solutie : Din moment ce problema ne cere generarea tuturor solutiilor, este evident ca vom avea nevoie de o abordare backtracking. #include<cstdio> int a[10],b[10]; void back(int k,int len) { if(k-1 == len) //afisam solutia { for(int i = 1; i <= len;i++) printf("%d ",a[i]); printf("\n"); } else { for(int i = 1; i <= len; i++) if(!b[i]) //daca valoarea nu-i folosita

{ a[k] = i; b[i] = 1; //o folosim back(k+1,len); //trecem la pasul urmator b[i] = 0; //o eliberam } } } int main() { freopen("permutari.in","r",stdin); freopen("permutari.out","w",stdout); int n; scanf("%d",&n); back(1,n); fclose(stdin); fclose(stdout); return 0; } Generarea tuturor combinarilor de n luate cate k Problema : Sa se genereze toate combinarile de N luate cate K in ordine lexicografica. Solutie : Din moment ce si aceasta problema ne cere generarea tuturor posibilitatilor este evident ca solutia este una ce are nevoie de o abordare backtracking. #include<cstdio> int a[19],b[19]; void back(int k,int len,int max) { if(k-1 == max) //afisam solutia { for(int i = 1; i <= max;i++) printf("%d ",a[i]); printf("\n"); } else { for(int i = 1; i <= len; i++) if(!b[i] && a[k-1] < i) //ne asiguram ca generam solutiile crescatoare si unice { a[k] = i; b[i] = 1; //o folosim back(k+1,len,max); //trecem la pasul urmator b[i] = 0; //o eliberam } } } int main() {

freopen("combinari.in","r",stdin); freopen("combinari.out","w",stdout); int n,k; scanf("%d %d",&n,&k); back(1,n,k); fclose(stdin); fclose(stdout); return 0; } Aplicatii Backtracking 1. Generarea aranjamentelor 2. Problema damelor 3. Problema turelor 4. Generarea produsului cartezian a n multimi 5. Sa se genereze n perechi de parantezari care se inchid corect 6. Cel mai lung prefix Concluzie Aceasta metoda este extrem de raspandita si de utila in cazul problemelor in care generarea tuturor solutiilor este necesara. De asemenea, in cazul concursurilor este una din cele mai populare modalitati de furare a catorva puncte. Referinte http://infoscience.3x.ro/c++/pbbacktracking.html http://infoarena.ro/problema/combinari http://infoarena.ro/problema/permutari http://en.wikipedia.org/wiki/Backtracking http://www.cse.ohio-state.edu/~gurari/course/cis680/cis680Ch19.html

Tags: backtracking problema damelor probleme rezolvate //problema damelor #include<iostream.h> #include<conio.h> #include<math.h> int st[20],n,k; void init() {st[k]=0;} int succesor() {if (st[k]<n) {st[k]++; return 1;

} else return 0;} int valid() {for(int i=1;i<k;i++) if(st[i]==st[k] || abs(st[k]-st[i])==abs(k-i)) return 0; return 1;} int sol() {return (k==n);} void tipar() {for(int i=1;i<=n;i++) cout<<st[i]; cout<<endl; } void bkt() {int as;k=1; init(); while(k>0) { do {} while ((as=succesor()) && !valid()); if (as) if (sol()) tipar(); else {k++;init();} else k--; } } main() {cout<<"n=";cin>>n; bkt(); getch(); } permutari #include<iostream.h> #include<conio.h> #include<stdio.h> int x[100],n,k; //k este este nivelul din stiva (indexul - vetorul solutie),curent int e_valid() {for(int i=1;i<=k-1;i++)//parcurg nivelurile anterioarenivelului curent if(x[i]==x[k]) return 0; return 1; } void afisare() {for(int i=1;i<=n;i++) cout<<x[i]<<" "; cout<<endl; } void back() {k=1; //pe primul nivel initial while(k>0)//cand k va descreste la 0 algoritmul se incheie

if(x[k]<n) {x[k]++; if(e_valid())//daca elementul incarcat este valid if(k==n)//verific daca am ajuns la solutia completa. afisare(); else //daca nu am solutia completa urc in stiva (maresc vectorul, adica pe k) {k++; x[k]=0;} } else k--; } void main() {clrscr(); cout<<"n="; cin>>n; back(); getch(); }

Metoda Backtracking. Probleme propuse 1. Problema permutarilor primelor n numere 2. Problema aranjamentelor 3. Problema combinarilor 4. Permutari , aranjamente, combinari de numere. 5. Se citesc n numere. Sa se genereze toate secventele din exact m dintre ele (m<n) astfel incat secventele sa contina numere distincte si doua numere alaturate sa nu aiba aceeasi paritate. Daca nu exista solutii se va afisa un mesaj; 6. Problema turelor 7. Problema damelor 8. n camile sunt numerotate de la 1 la n sunt aranjate in sir indian. Sa se rearanjeze camilele astfel incat fiecare camila sa aiba in fata o camila diferita de configuratia initiala. 9. Sa se genereze produsul cartezian a n multimi. Pentru fiecare multime se cunoaste numarul de elemente. Daca o multime a p elemente atunci va contine valorile de la 1,2 la p. Exn=3, p1=2, p2=3, p3=3 p4=4 Atunci: {1,2} x {1,2,3} x {1,2,3}x{1,2,3,4}= (1 1 1 1 ) (1 1 1 2 ) (1 1 1 3 ) (1 1 1 4 ) (1 1 2 1 ) (1 1 2 2 ) (1 1 2 3 ) (11 2 4 ) (1 1 3 1 )(1 1 3 2 ) (1 1 3 3 ) (1 1 3 4 ) (1 2 1 1 ) (1 2 1 2 ) (1 2 1 3 ) (1 2 1 4 ) (1 2 2 1 ) (1 2 2 2 ) (1 2 2 3 ) (1 2 2 4 ) (1 2 3 1 ) (1 2 3 2) (1 2 3 3 ) (1 2 3 4 ) (1 3 1 1 ) (1 3 1 2 ) (1 3 1 3 ) (1 3 1 4 ) (1 3 2 1 ) (1 3 2 2 ) (1 3 2 3 ) (1 3 2 4 ) (1 3 3 1 ) (1 3 3 2 ) (1 3 3 3 ) (1 3 3 4 ) (2 1 1 1 ) (2 1 1 2 ) (2 1 1 3 ) (2 1 1 4 ) (2 1 2 1 ) (2 1 2 2 ) (2 1 2 3 ) (2 1 24 ) (2 1 3 1 ) (2 1 3 2 ) (2 1 3 3 ) (2 1 3 4 )

(2 2 1 1 ) (2 2 1 2 ) (2 2 1 3 ) (2 2 1 4 ) (2 2 2 1 ) (2 2 2 2 ) (2 2 2 3 ) (2 2 2 4 ) (2 2 3 1 ) (2 2 3 2 ) (2 2 3 3 ) (2 2 3 4 ) (2 3 1 1 ) (2 3 1 2 ) (2 3 1 3 ) (2 3 1 4 ) (2 3 2 1 ) (2 32 2 ) (2 3 2 3 ) (2 3 2 4 ) (2 3 3 1 ) (2 3 3 2 ) (2 3 3 3 ) (2 3 3 4 ) N copii se aseaza in sir indian. Se cunosc numele celor n copii. Sa se gaseasca toate posibilitatile de aranjare in sir. 10. Gigel are n cartonase (n<=10). Pe fiecare este scrisa o cifra de la 1 la 9. Uilizand doua tipuri de cartonase cu + si - vrea sa obtina rezultatul 2. Care sunt solutiile pentru n citit? 11. Sa se genereze n perechi de paranteze care se inchid corect. Exemplu: n=3: ( ( ( ) ) ) ( ( ) ( ) ) ( ) ( ( ) ) etc 12. Se cer toate solutiile de asezare in linie a m caini si n pisici astfel incat sa nu existe o pisica intre doi caini 13. Sa se genereze toate numerele palindrome de lungime n 14. Sa se genereze toate partitiile unui numar (sa se descompuna in suma de numere). Ex: n=4 Solutii: 1111 112 13 22 16. Sa se decompuna un numar in suma de numere prime. Generati toate solutiile.
17. N copii se aseaza in cerc. Se cunosc numele celor n copii. Sa se gaseasca toate posibilitatile

de rearanjare in cerc. 18. N copii se aseaza in sir indian. Se cunosc numele celor n copii. Sa se gaseasca toate posibilitatile de aranjare in sir astfel incat un baiat sa urmeze dupa cel mult doua fete alaturate. 19. N copii au fost asezati in sir indian. Se cunoaste configuratia initiala. Sa se reaseze copiii astfel incat fiecare copil sa urmeze dupa un alt copil, diferit de cel din configuratia initiala. 20. Se citeste un numar. Sa se genereze toate numerele avand aceleasi cifre ca el. Care este cel mai mare? 21. N copii au fost asezati in sir indian. Se cunoaste configuratia initiala. Sa se reaseze copiii astfel incat fiecare copil sa se situeze intre alti copii, diferiti de cei din configuratia initiala. 22. Plata unei sume in bancnote de n tipuri. Solutia cea mai lunga (scurta) 23. Problema drapelelor. Sa se afiseze ca drapel 24. Sa se genereze anagramele unui cuv 25. Sa se genereze toate triunghiurile de perimetru n 26. Intre n persoane care stau pe scaune s-au iscat conflicte. Acestea stau pe scaune numerotate de la 1 la n. Scrieti un program care sa afiseze toate modurile posibile de reasezare a persoanelor astfel incat sa nu se gaseasca alaturi doua persoane in conflict. 27. Sa se genereze toate matricile binare (avand 0 si 1) simetrice cu nxn componente. 28. Sa se genereze o secventa de n sunete avand lungimea p care respecto o anumita conditie 29. La un spectacol trebuie sa interpreteze cate o poezie copiii A, B, C, D, E astfel incat copilul D sa recite inainte de A si B. Sa se genereze toate posibilitatile de recitare a poeziilor. 30. Sa se genereze toate numerele de lungime n formate doar cu cifre pare / impare 31. Scrieti un program care sa afiseze toate numerele de n (n<=10) cifre, formate numai din cifre distincte si care sunt divizibile cu 4. 32. Sa se aranjeze in toate modurile elementele unui vector a[1],a[2]a[n] formand secvente de lungime p, astfel incat fiecare element sa apara de cel mult doua ori

33. Sa se genereze toate cuvintele de lungime p, distincte / nedistincte, care se pot forma cu literele alfabetului dintr-o multime data 34. Pe o tabla de dimensiune nxn se gasesc n regi. Sa se gaseasca toate posibilitatile de aranjare a regilor pe tabla astfel incat oricare 2 regi sa nu se atace. Obs. Fiecare rege se va gasi pe alta linie. 35. Problema partitiilor unui numar 36. Submultimile unui numar 37. a) Fie sirul primelor n numare naturale (n citit de la tastatura). Sa se insereze inainte de fiecare semnul + sau minus. Pentru fiecare solutie astfel generata se va afisa valoarea expresiei. Ex pt n =3: +1+2+3=6 +1+2-3=0 +1-2+3=2 etc b) sa sedetermine solutiile pentru care expresia este egala cu x. Daca nu exista solutii sa se afiseze un mesaj 38. a) Fie n numare naturale (n citit de la tastatura) citite de la tastatura. Sa se insereze inainte de fiecare semnul + sau minus. Pentru fiecare solutie astfel generata se va afisa valoarea expresiei. Ex pt n =3 si numerele 2 5 4 se vor genera expresiile: +2+5+4=11 +2+5-4=3 +2-5+4=1 etc. b) sa sedetermine solutiile pentru care expresia este egala cu x. Daca nu exista solutii sa se afiseze un mesaj 39. La o cofetarie se comercializeaza n sortimente de prajituri. Sa se determine toate variantele de a face pachete cu cate p prajituri diferite. Scrieti un program care permite citirea de la tastatura a celor n sortimente de prajituri si afiseaza variantele solutie precum si numarul acestora. 40. Fiind data o multime de n cuburi, fiecare cub fiind caracterizat de lungimea laturii si culoarea sa, sa se scrie un program care sa genereze toate turnurile care se pot forma cu p cuburi astfel incat doua cuburi vecine sa nu aiba aceeasi culoare iar deasupra unui cub sa nu se poata aseza un cub cu latura mai mare. 41. Un grup de copii are la dispozitie n cartonase cu n cuvinte disticte pentru jocul "cerc de cuvinte". In acest joc un copil trebuie sa spuna un cuvant care sa aiba primele doua litere identice cu ultimele doua ale cuvantului spus de predecesorul lui. fiind dat un cuvant de inceput pentru joc, afisati varianta cu cele mai multe cuvinte care se pot obtine cu ajutorul cartonaselor date. Observatie: un sir de cuvinte nu va contine un cuvant de mai multe ori. 42. O persoana a uitat numarul de telefon al unui prieten. Stie doar ca numarul are 6 cifre, incepe cu 4 si contine 3 zerouri dintre care doua sunt alaturate. fisati toate variantele pe care trebuie sa le incerce pentru a vorbi cu prietenul sau. 43. La o masa rotunda sunt n persoane de diverse nationalitati, pentru fiecare persoana precizandu-se doua limbi straine cunoscute de ea. Se cere sa ajutati organizatorii mesei rotunde sa aranjeze persoanele astfel incat fiecare sa poata conversa atat cu cea din stanga cat si cu cea din dreapta. 44. Sa se genereze numerele mai mici decat n citit care trecute in baza 2 au in componenta lor exact p cifre de 1. 45. Teste la geografie. Pentru lucrarea de control profesoara de geografie a pregatit n teste. In clasa sunt p elevi (p>n). Sa se genereze toate posibilitatile de a imparti testele celor p elevi astfel incat fiecare test sa fie rezolvat de macar un elev.

46. Sa se genereze toate drapelele tricolore care se pot forma cu n culori (eventual impunand conditii : in mijloc sa fie o anumita culoare, o culoare sa nu stea langa alta culoare etc 47. Produsul cartezian a n multimi impunand conditia ca suma elementelor dintr-o solutie sa fie egala cu un S citit 48. Sa se genereze toate submultimile de cate k elemente care se pot forma cu numerele 1,2n (sau a[1],a[2]a[n]), cu conditia ca fiecare element sa fie divizibil cu un numar d dat. 49. Sa se rearanjeze elementele unui vector a[1],a[2]a[n] in toate modurile posibile, astfel incat oricare doua alaturate sa nu fie consecutive in sirul initial 50. Sa se aranjeze n margele de m culori astfel incat oricare doua margele alaturate sa aiba culori diferite 51. Sa se genereze toate numerele de lungime p care sunt supermultiple de p (atat numerele cat si toate prefixele lor sa fie multiplu de p) 52. La un festival de muzica usoara s-au inscris n melodii codificate cu numere de la 1 la n. Stiind ca in prima zi intra in concurs k melodii, sa se afiseze toate posibilitatile de a stabili ordinea intrarii in concurs a melodiilor in prima zi, stiind ca melodiile de coduri c1 si c2 trebuie sa intre in prima zi, a doua respectiv penultima 53. Sa se afiseze toate numerele de lungime p<=9 cu proprietatea ca au suma cifrelor egala cu x dat 54. Sa se afiseze toate submultimile cu p elemente dintre elementele a[1],a[2]a[n] cu proprietatea ca suma elementelor din multime este un numar divizibil cu x dat 55. Sa se afiseze toate modurile in care se poate forma un grup de p persoane dintr-un grup de n persoane, dintre care l persoane sa fie femei 56. La un concurs se prezinta n concurenti din m tari. Sa se stabileasca ordinea intrarii in concurs a celor n concurenti astfel incat doi concurenti din aceeasi tara sa nu urmeze unul dupa altul 57. Sa se aranjeze elementele multimii {A,R,G,V} in grupuri de cate n (n par) astfel incat doua caractere identice sa nu fie alaturate si R sa apara de exact n/2 ori 58. Sa se genereze toate numerele de lungime n formate doar cu cifre pare / impare 59. Sa se genereze toate numerele de lungime n divizibile cu x dat 60. Sa se determine toate numerele de lungime n care sunt egale cu inversele lor 61. Sa se determine toate modurile in care poate fi capsat un bilet, stiind ca pozitiile posibile sunt de forma: *** *** *** si se pot perfora p1<=k Biletul poate fi introdus pe oricare din fete. 1. Sunt 2n copii de inaltimi diferite. Sa se aseze copiii pe 2 randuri astfel: - pe primul rand copiii sa fie asezati in ordinea crescatoare a inaltimii - copiii de pe al doilea rand sa fie mai inalti decat cei din fata lor 2. un pion se poate deplasa pe o tabla dreptunghiulara cate o casuta pe orizontala sau pe varticala. Se dau coordonatele initiale, coordonatele finale si de cate ori trebuie sa treaca pionul prin fiecare casuta. Sa se genereze toate solutiile. De fiecare data se afiseaza traseul de parcurs. Exemplu 112110 002220 000010 000000 din 1 1 pana in 1 5 o solutie este:

1 1, 1 2, 1 3, 2 3, 2 4 , 2 5, 3 5, 2 5, 2 4, 2 3, 1 3, 1 4, 1 5. 62. Sa se genereze toate solutiile naturale nenule ale ecuatiei 4x+y+3yz=100 63. sa se genereze toate codurile morse de lungime n coduri reprezentate prin sau . Astfel incat intr-o secventa sa nu existe doua puncte alaturate. Pentru fiecare semn se va genera un sunet. 64. Sa se genereze toate secventele in cod binar de lungime n. Pentru fiecare secventa se va genera numarul asociat in baza 10.Sa se genereze toate codurile 65. Sa se genereze toate numerele naturale ale caror cifre se gasesc printre cifrele lui x citit si au lungimea cel mult egala cu lungimea lui x. Cifrele se pot repeta 66. La Masa Rotunda sunt n cavaleri. Fiecare dintre ei are cel putin un dusman printre ceilalti. Sa se gaseasca toate posibilitatile de a-i aseza la masa astfel incat doi vavaleri dusmani sa nu fie vecini. Se citesc cele m perechi de dusmani de la tastatura (fisier) 67. Fie o harta cu n tari. M perechi de tari sunt vecine (se cunosc perechile de tari vecine). Sa se coloreze harta astfel incat oricare doua tari alaturate sa fie colorate diferit. 68. Un comis voiajor trebuie sa ajunga la n case. Intre cele n case exista m dumuri (un drum este dat ca o pereche de case vecine). Sa se genereze toate posibilitatile de parcurgere a celor n o singura data case astfel incat comis voiajorul sa ajunga inapoi de unde a plecat. Casa de la care se pleaca este casa p. 69. In cate moduri poate ajunge un pion de pe prima linie a unei table bidimensionale cu n linii si n coloane pe ultima linie a tablei. Se cunoaste coloana de plecare p. Pionul se poate deplasa numai pe o casuta alaturata si numai pe o linie mai mare. 70. Sa se determine partitiile unui numar pt care suma inverselor obtinute este subunitara. Ex. n=5 3+2=5 si 1/3+1/2<1. 71. Se citeste un numar natural. Sa se determine toate numerele avand aceleasi cifre sau o parte din cifre si care sunt divizibile cu p citit 72. Sa se determine toate numerele cu cifre distincte. Cate astfel de numere sunt? 73. Sa se genereze toate numerele avand cifre distincte de la 0 la p. Numarul de cifre poate fi >=1 si <= p+1. Cate astfel de numere sunt? 74. Sa se determine cate numere cu cifre distincte sunt. Backtracking in plan Fie urmatoare problema: un soricel se gaseste intr-un labirint de forma dreptunghiulara cu m linii si n coloane. Peretii sunt marcati cu 1 si culoarele cu 0. Se cunosc coordonatele initiale ale soricelului: Li, Ci. Sa se determine toate posibilitatile pe care le are soricelul pentru a iesi din labirint. Soricelul poate avansa pe 4 directii cate o celula (sus, dreapta , jos, stanga). O astfel de problema presupune o abordare Backtracking in plan. Traseul soricelului va fi retinut de un vector cu doua campuri: coordonatele x si y. Vom defini un tip struct: struct pozitie {int x,y;}; si vom declara un vector care retine drumul: pozitie d[50]; Pentru generarea unui drum vom defini un subprogram recursiv oid ies(int x,int y) care primeste ca parametri coordonatele unei componente din matrice. Initial se apeleaza pentru coordonatele initiale ale soricelului. O componenta din matrice va putea apartine drumului daca evident este culoar (a[x][y]=0). O celula a matricii determinata ca apartinand drumului se marcheaza cu 2 (pentru a preveni ciclarile): a[x][y]=2; Se incarca valoarea corespunzatoare in vectorul d pe nivelul curent: d[k].x=x; d[k].y=y;

De fiecare data cand s-a determinat o noua celula ca apartinand drumului se determina daca s-a ajuns la solutie (conditie care difera de la o problema la alta). In cazul probemei noastre se iese din labirint cand se ajunge la linia 0 sau coloana 0 sau linia m+1 sau coloana n+1. testul este: if((x<1)||(x>m)||(y<1)||(y>n)) tipar(k); In caz afirmativ se tipareste (se afiseaza vectorul d si/sau matricea a) altfel (daca solutia este incompleta) se incearca parcurgerea, pe rand, a celor 4 celule alaturate. Acest lucru se realizeaza prin autoapelul functiei ies pe cele patru directii: ies(x-1,y); ies(x,y+1); ies(x+1,y); ies(x,y-1); Observatie: vectorul d functioneaza ca o stiva cu doua campuri. La revenire din apel se elibereaza celula pentru a o putea accesa si in cadrul altor prelucrari: a[x][y]=0 si se elibereaza componenta drumului k=k-1 (practic se coboara in stiva). void ies(int x,int y) {if(a[x][y]==0) {k++; a[x][y]=2; d[k].x=x; d[k].y=y; if((x<1)||(x>m)||(y<1)||(y>n)) tipar(k); else {ies(x-1,y); ies(x,y+1); ies(x+1,y); ies(x,y-1); } a[x][y]=0; //la revenire din apel demarchez celula pentru a o putea //accesa si in cadrul altei prelucrari k--; //eliberez componenta din vectorul drumului } } Fie urmatorul labirint: m=6 n=10 Li=4, Ci=3 1111011111 1111011111 1111011111 1100000000 1111111011 1111111011 Solutiile vor fi: solutia 1 (4,3) (4,4) (4,5) (3,5) (2,5) (1,5) (0,5) 1111211111 1111211111 1111211111

1122200000 1111111011 1111111011 solutia 2 (4,3) (4,4) (4,5) (4,6) (4,7) (4,8) (4,9) (4,10) (4,11) 1111011111 1111011111 1111011111 1122222222 1111111011 1111111011 solutia 3 (4,3) (4,4) (4,5) (4,6) (4,7) (4,8) (5,8) (6,8) (7,8) 1111011111 1111011111 1111011111 1122222200 1111111211 1111111211 Programul complet este: #include<fstream.h> #include<conio.h> struct pozitie {int x,y;}; int a[20][20];//labirintul int k,n,m,Li,Ci,nr_sol; pozitie d[50]; void afis_mat() //afiseaza matricea {cout<<endl; for(int i=1;i<=m;i++) {for(int j=1;j<=n;j++) cout<<a[i][j]<<" "; cout<<endl;} } void tipar(int k) //tipareste vectorul drum {nr_sol++; cout<<"solutia "<<nr_sol<<endl; for(int i=1;i<=k;i++) cout<<"("<<d[i].x<<','<<d[i].y<<") "; afis_mat(); getch(); cout<<endl;} void ies(int x,int y) //genereaza drumul {if(a[x][y]==0) {k++; a[x][y]=2; d[k].x=x; d[k].y=y; if((x<1)||(x>m)||(y<1)||(y>n))

tipar(k); else {ies(x-1,y); ies(x,y+1); ies(x+1,y); ies(x,y-1); } a[x][y]=0; //la revenire din apel demarchez celula pentru a o putea //accesa si in cadrul altei prelucrari k--;//eliberez componenta din vectorul drumului } } void citire() { fstream f; f.open("labir.txt",ios::in); if(f) cout<<"ok"; else cout<<"eroare la deschidere"; //Citesc matricea ce reprezinta labirintul f>>m>>n; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) f>>a[i][j]; f>>Li>>Ci; //coordonatele punctului in care se afla soricelul } void main() {clrscr(); k=0; citire(); ies(Li,Ci); afis_mat(); getch(); } Probleme propuse: 1. aceeasi problema ca in exemplu cu diferenta ca soricelul poate avansa in celule alaturate pe cele 8 directii posibile 2. Un soricel se gaseste intr-un labirint de forma dreptunghiulara cu m linii si n coloane. Peretii sunt marcati cu 1 si culoarele cu 0. Se cunosc coordonatele initiale ale soricelului: Li, Ci. Sa se determine toate posibilitatile pe care le are soricelul pentru a iesi ajunge la cascaval. Se cunosc coordonatele cascavalului: Lf,Cf. 3. Aceeasi problema ca la 2 cu diferenta ca se afiseaza doar cea mai scurta solutie. 4. Un labirint dreptunghiular cu m linii si n coloane contine culoare (reprezentate prin 0) si pereti (reprezentati prin -1). Se dau coordonatele initiale ale unui soricel si coordonatele finale , unde trebuie sa ajunga. Pe culoare se gasesc bucati de branza pt care se cunoaste greutatea in grame. a) Sa se genereze toate solutiile., pt fiecare se afiseaza cantitatea consumata

Sa se afiseze soultia cea mai consistenta Indicatie: se vor marca cu -2 celulele parcurse si se vor retine in vectorul drum inclusiv cantitatea condumata. Matricea se borda cu pereti (-1). 5. Pe o tabla de forma dreptunghiulara se afla un cal. Se cunosc coordonatele initiale ale calului. Acesta trebuie sa ajunga intr-o pozitie finala sarind numai sub forma sariturii calului. Stiind ca numai anumite celule sunt permise sariturii (acestea sunt marcate) sa se determine ce posibilitati sunt ca sa se ajunga in pozitia finala. 6. Romeo si Julieta se gasesc intr-un labirint (se cunosc culoarele si peretii si coordonatele celor doi indragostiti). a)Exista posibilitatea ca Romeo sa ajunga la Julieta? b)in cazul in care cei doi se indreapta simultan unul catre celalat pentru fiecare solutie se va afisa locul intalnirii (coordonatele celulelor alaturate sau celulei comune de intalnire) <a href='http://ads.3xmedia.ro/www/delivery/ck.php?n=aee207a1' target='_blank'><img src='http://ads.3xmedia.ro/www/delivery/avw.php?zoneid=20&amp;n=aee207a1' border='0' alt='' /></a> PROBLEME BACKTRACKING IN PLAN 1. Sa se completeze o tabla de 5*5 cu saritura calului. Iata doua solutii: 1 24 13 13 18 18 7 7 14 19 8 8 23 25 12 12 9 9 2 2 25 23 6 6 17 17 20 3 20 3 15 10 15 10 4 4 21 21 11 16 11 16 22 5 22 5

b)

Aflati numarul de solutii si afisati tablele. 2.Se da un tablou bidimensional (m linii, n coloane si m*n componente) cu elemente distincte. Se dau si coordonatele primului punct. Ss se genereze un traseu in matrice pornind de la punctul dat astfel incat suma k*a[i][j] (unde k=1 n*m ) sa fie maxima. In matrice se poate avansa numai la elemente vecine (pe cele 8 directii). Ex: n=m=4;pozitia initiala : linia 3,coloana 2; 1 14 3 4 3 12 2 15 5 11 10 1 9 16 8 6 7

Suma maxima va fi: 1*1+2*2+3*3++16*16. 3.Ali Baba

Ali Baba i-a surprins pe cei 40 de hoti, in timp ce cotrobaiau printre comorile lui. Hotii erau multi, el era singur, asa ca a incercat sa negocieze cu ei. Avea o ladita speciala, pe care era notat numarul de diamante aflate in aceasta, un numar avnd cel mult 40 de cifre, intr-o baza b. Ali Baba a propus conducatorului hotilor sa elimine din numar b cifre, dupa care poate sa plece cu atatea diamante cate reprezinta numarul ramas. Hotul, mai intai a stabilit valoarea cea mai mica posibila b, deoarece a vrut sa stabileasca un numar cat mai mic posibil de cifre pe care urmeaza sa le elimine. Apoi a inceput tierea cifrelor. In timpul eliminarii a urmarit ca numarul ramas sa fie cat se poate de mare. Scrieti un program care il ajuta pe hot(Ali Baba are destule comori). Date de intrare Pe prima linie a fisierului de intrare ALIBABA.IN se afla un sir de cifre, nedespartite prin spatii. Date de iesire Pe prima linie a fisierului de iesire ALIBABA.OUT se va scrie pe fiecare cate un numar, reprezentand numasrul ramas dupa eliminarea unei cifre. Restrictii si precizari 2<=b<=10 Exemplu ALIBABA.IN 323332112 ALIBABA.OUT 4 33332112 333212 33322 3332 Un labirint dreptunghiular cu m linii si n coloane contine culoare (reprezentate prin 0) si pereti (reprezentati prin 1). Se dau coordonatele initiale ale unui soricel si coordonatele finale , unde trebuie sa ajunga. Soricelul poate avansa sus, jos , stanga sau dreapta.(Incercati si cu cele 8 directii) 1. Sa se genereze toate solutiile. 2. Sa se afiseze soultia cea mai lunga (scurta) Un labirint dreptunghiular cu m linii si n coloane contine culoare (reprezentate prin 0) si pereti (reprezentati prin 1). Se dau coordonatele initiale ale unui soricel care trebuie sa iasa din labirint.SA se genereze toate solutiile Un labirint dreptunghiular cu m linii si n coloane contine culoare (reprezentate prin 0) si pereti (reprezentati prin -1). Se dau coordonatele initiale ale unui soricel si coordonatele finale , unde trebuie sa ajunga. Pe culoare se gasesc bucati de branza pt care se cunoaste greutatea in grame. 1. Sa se genereze toate solutiile., pt fiecare se afiseaza cantitatea consumata 2. Sa se afiseze soultia cea mai consistenta Un broscoi se gaseste pe o frunza de nufar pe un lac. Broscoiul poate sari numai sub forma sariturii calului si nu trebuie sa cada in apa. Pe lac se gasesc mai multe frunze. Se da dimensiunea lacului (ca matrice mxn) si coordonatele frunzelor. Ajutati-l pe roscoi sa iasa din lac. (si alte variante: de la o frunza la alta etc)

Problema fotografieiMetoda backtracking Noiuni teoretice Prezentare general Aceast metod general de programare se aplic problemelor n care soluia se poate reprezenta sub forma unui vector X = (x1, ..., xn)S unde S = S1 x ... x Sn , unde mulimile S1, ...,Sn sunt mulimi finite avnd |Si| = si elemente. Pentru fiecare problem concret sunt date anumite relaii ntre componentele x1 , ... xn ale vectorului X, numite condiii interne. Mulimea finit S = S1 x S2 x... x Sn se numete spaiul soluiilor posibile (este un produs cartezian). Soluiile posibile care satisfac condiiile interne se numesc soluii rezultat. Ceea ce ne propunem este de a determina toate soluiile rezultat, cu scopul de a le afia sau de a alege dintre ele una care maximizeaz sau minimizeaz o eventual funcie obiectiv dat. O metoda simpl de determinare a soluiilor rezultat const n a genera ntr-un mod oarecare toate soluiile posibile i de a verifica dac ele satisfac condiiile interne. Dezavantajul const n faptul c timpul cerut de aceast investigare exhaustiv este foarte mare. Astfel, chiar pentru |Si| = 2, " i, timpul necesar este de ordinul 2n, deci exponenial. Metoda backtracking urmrete s evite generarea tuturor soluiilor posibile. n acest scop, elementele vectorului X primesc pe rnd valori n sensul c lui xk i se atribuie o valoare numai dac au fost atribuite deja valori lui x1 ,... xk-1 . Mai mult, odat o valoare pentru xn stabilit, nu se trece direct la atribuirea de valori lui xk+1 , nendeplinirea lor exprimnd faptul c oricum am alege xk+1,...,xn nu vom putea ajunge la o soluie rezultat, adic o condiie pentru care condiiile interne s fie satisfcute. Evident c n cazul nendeplinirii condiiilor de continuare va trebui s facem o alt alegere pentru xk sau dac Sk a fost epuizat s micorm pe k cu o unitate ncercnd s facem o nou alegere pentru xk etc.; aceast micorare a lui k d numele metodei, ilustrnd faptul c atunci cnd nu mai putem avansa, urmrim napoi secvena curent din soluie. Este evident c ntre condiiile de continuare i condiiile interne exist o strns legtur. O bun alegere pentru condiiile de continuare are ca efect o important reducere a numrului de calcule. Metoda backtracking poate fi reprezentat uor, pe un arbore construit astfel: - nivelul 1 conine rdcina; - din orice vrf de pe nivelul k pleac sk muchii spre nivelul k+1 etichetai cu cele sk muchii ale lui Sk. Nivelul n+1 va conine s1 s2 ... sn vrfuri. Pentru fiecare vrf de pe nivelul n+1, etichetele muchiilor coninute pe drumul ce leag rdcina de acest vrf reprezint o soluie posibil. Exemplu - S considerm problema submulimilor de sum dat care const n urmtoarele: Fie A = (a1, a2, ..., an) cu ai > 0, " i. Fie MR+. Se caut toate submulimile B ale lui A pentru care suma elementelor este M. Pentru a putea realiza problema prin metoda backtracking vom reprezenta soluia sub forma x = (x1, ..., xn) unde xi = 1 dac aiB i xi = 0 n caz contrar. Sa ne situm n ipoteza ca n=4. Arborele ataat metodei backtracking este urmtorul:

Ctigul obinut prin introducerea condiiilor de continuare const n faptul c, dac ntr-un vrf ele nu mai sunt verificate, se va renuna la parcurgerea subarborelui care are ca rdcin acest vrf. Acest exemplu permite prezentarea unei variante a metodei backtracking. ntr-adevr, s considerm drept soluie posibil o valoare k n mpreun cu k-uplul (x1, ..., xk) unde pentru i {1, ..., k}, xi reprezint indicele elementului pe care l introducem n B. Evident xi xj pentru ij. Pentru a nu se repeta soluii, vom presupune x1<x2<...<xn . Obinem astfel urmtorul arbore n care fiecare vrf corespunde unei soluii posibile.

Diferitele variante ale metodei backtracking nu schimb esena ei care const n faptul c este reprezentabil pe un arbore care este parcurs "cobornd" n arbore numai dac exist anse de a ajunge la o soluie rezultat. n continuare, problemele care vor fi prezentate vor urma o schema general i anume: - se va testa dac am obinut o soluie, situaie n care acesta se va reine; - dac nu am obinut soluie se ncearc plasarea unui nou element n vectorul soluie cu respectarea condiiilor de continuare; - dac nu se reuete plasarea unui nou element i spaiul valorilor posibile de plasat s-a epuizat, se revine la poziia anterioar i se ncearc s se plaseze pe ea un alt element. Faptul c dup plasarea unui element n vectorul soluie algoritmul presupune plasarea unui element pe poziia imediat urmtoare, adic de fapt reluarea algoritmului, conduce posibilitatea abordrii recursive a algoritmilor de tip backtracking. Acest lucru permite o scriere mult mai scurt i mai simpl a algoritmilor i apoi a programelor care i implementeaz. Astfel, general, un algoritm backtracking poate fi prezentat astfel: Subalgoritm back (k) pentru fiecare valoare i din multimea Sk execut xki dac X respect condiiile interne atunci dac X este solutie atunci afiseaz X altfel

apeleaz back(k+1) sfdac sfdac sfpentru n funcie de problema concret, n algoritmul descris mai sus se vor modifica doar instruciunea pentru, condiiile interne i cele de soluie, structura algoritmului pstrndu-se. Probleme de generare. Oportunitatea utilizrii metodei backtracking Problemele care se rezolv prin metoda backtracking pot fi mprite n mai multe grupuri de probleme cu rezolvri asemntoare, in funcie de modificrile pe care le vom face n algoritm. Principalele grupuri de probleme sunt: a) probleme n care vectorul soluie are lungime fix i fiecare element apare o singur dat n soluie; b) probleme n care vectorul soluie are lungime variabil i fiecare element poate s apar de mai multe ori n soluie; c) probleme n plan, atunci cnd spaiul n care ne deplasm este un tablou bidimensional. Vom prezenta n cele ce urmeaz cteva probleme care pac parte din primul grup. Cele mai cunoscute sunt: generarea permutrilor unei mulimi generarea aranjamentelor unei mulimi generarea submulimilor unei mulimi generarea submulimilor cu m elemente ale unei mulimi (combinri) generarea produsului cartezian a n mulimi generarea tuturor secvenelor de n (par) paranteze care se nchid corect. colorarea rilor de pe o hart astfel nct oricare dou ri vecine s aib culori diferite aranjarea a n regine pe o tabl de ah de dimensiune n fr ca ele s se atace. Toate problemele din acest grup au particularitatea c soluia se obine atunci cnd vectorul soluie ajunge s conin un anumit numr de elemente. Vom exemplifica modul de lucru al metodei backtracking pentru problema damelor. Aranjarea reginelor. Dndu-se o tabl de ah de dimensiune nxn (n>3) s se aranjeze pe ea n regine fr ca ele s se atace. Reamintim c o regin atac linia, coloana i cele 2 diagonale pe care se afl. n figura de mai jos celulele colorare mai nchis sunt atacate de regina poziionat unde indic litera R.

R n algoritmul de mai sus avem de particularizat urmtoarele: Instruciunea pentru fiecare valoare i din mulimea Sk execut va fi nlocuit cu o instruciune pentru care parcurge toate valorile de la 1 pn la n. Condiia de a putea plasa o regin pe poziia k este un pic mai complicat i presupune verificarea ca s nu se atace cu nici una dintre celelalte k-1 regine deja plasate pe tabla. Dac pe poziia k din vectorul X punem o valoare ea va reprezenta coloana pe care se plaseaz pe tabl regina k. Condiiile devin astfel: x[i]x[k] i |k-i||x[k]-x[i]| cu i de la 1 la k-1 i |x| reprezentnd modului lui x. Condiia de soluie este simpl i presupune plasarea corect a tuturor celor n regine. Programele Pascal si C++ rezultate prin implementarea algoritmului descris mai sus urmtoarele: Varianta C/C++

Varianta Pascal var x:array[1..100] of byte; #include<iostream.h> n:byte; #include<math.h> nrsol:word; int x[100],n,nrsol; procedure scriesol; void scriesol () var i,j:byte; { int i,j; begin nrsol++; inc(nrsol); cout<<"Solutia a "<<nrsol<<" este"; writeln('Solutia a',nrsol,'este'); for(i=1;i<=n;i++) for i:=1 to n do begin { cout<<endl; writeln; for(j=1;j<=n;j++) for j:=1 to n do if if (x[j]==i) cout<<"X "; x[j]=i then write('X',' else cout<<"O "; ') else } write('O',' '); } end; int potcont(int k) end; { int i; function potcont(k:byte):boolean; for(i=1;i<=k-1;i++) var i:byte; if (x[i]==x[k] || k-i==abs(x[k]-x[i])) return 0; atac:boolean; return 1; begin } atac:=false; void back(int k) for i:=1 to k-1 do { if(x[i]=x[k]) or (k-i=abs(x[k]-x[i])) then int i; atac:=true; for(i=1;i<=n;i++) potcont:=not atac; { end; x[k]=i; procedure back(k:byte); if (potcont(k)) var i:byte; if (k==n) scriesol(); begin else back(k+1); for i:=1 to n do } begin } x[k]:=i; void main() if potcont(k) then { if k=n then scriesol cin>>n; else back(k+1); nrsol=0; end; back(1); end; cout<<nrsol<<" solutii"; begin } read(n); nrsol:=0; back(1); writeln(nrsol,'solutii'); end. Din al doilea grup fac parte probleme a cror condiie de soluie nu se mai pune asupra numrului de elemente din vectorul X, ci asupra elementelor din soluie. Exemple: partiiile unui numr natural n partiiile unei mulimi

plata unei sumei cu monede de valori date Partiiile unui numr natural. Fie n>0, natural. S se scrie un program care s afieze toate partiiile unui numr natural n. Numim partiie a unui numr natural nenul n o mulime de numere naturale nenule {p1, p2, , pk} care ndeplinesc condiia p1+p2+ +pk = n. Ex: pt n = 4 programul va afia: 4 = 1+1+1+1 4 = 1+1+2 4 = 1+3 4 = 2+2 4=4 Observaii: - lungimea vectorului soluie cel mult n; exist posibilitatea ca soluiile s se repete; condiia de final este ndeplinit atunci cnd suma elementelor vectorului soluie este n. Am menionat mai sus c vom folosi doi parametri, unul pentru poziia n vectorul soluie i un al doilea n care avem sumele pariale la fiecare moment. Avem determinat o soluie atunci cnd valoarea celui de-al doilea parametru este egal cu n. n aceast situaie la fiecare plasare a unei valori n vectorul sol valoarea celui de al doilea parametru se mrete cu elementul ce se plaseaz n vectorul soluie. Apelul procedurii back din programul principal va fi back(1, 0). Exist i posibilitatea de a apela procedura back din programul principal back(1, n) i valoarea celui de al doilea parametru se decrementeaz cu elementul ce se plaseaz n vectorul sol, iar o soluie avem cnd acest parametru este zero. Indiferent care modalitate este aleas acest al doilea parametru ne permite s optimizm puin programul n sensul c putem considera nite condiii de continuare mai strnse. Varianta C/C++ Varianta Pascal program Partitii_nr_natural; #include<iostream.h> var n, ns: byte; int n, ns,sol[20]; sol: array[1..20] of byte; void afis(int l) procedure afis(l: byte); { int i; var i: byte; ns++; begin cout<<"Solutia nr. "<< ns<<" : "; inc(ns); for(i=1;i<=l;i++) cout<<sol[i]<<" "; write 'Solutia ', ns, ' : '); cout<<endl; for i:=1 to l do } write(sol[i]:3); void back(int i, int sp) writeln; { int j; end; if (sp==n) afis(i-1); procedure back(i, sp: byte); else for(j=1;j<=n-sp;j++) var j: byte; if (j>=sol[i-1]) begin { if sp = n then afis(i-1) sol[i]=j; else for j:=1 to n-sp do back(i+1, sp+j); if (j>=sol[i-1]) } then begin } sol[i]:=j; void main() back(i+1, sp+j) end; {

end; begin read(n); ns:=0; back(1,0); writeln(ns,'solutii'); end.

cin>>n; ns=0; back(1,0); cout<<ns<<" solutii"; }

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.

Varianta C/C++ Varianta Pascal const dx:array[1..8] of -2..2=(-1,1,2,2,1,-1,- #include<fstream.h> 2,-2); const int dx[8]={-1,1,2,2,1,-1,-2,-2}; dy:array[1..8] of -2..2=(-2,-2,-1,1,2,2,1,-1); const int dy[8]={-2,-2,-1,1,2,2,1,-1};

var a:array[1..10,1..10] of integer; n:integer; f:text; procedure cit; var i,j :integer; begin readln(n); for i:=1 to n do for j:=1 to n do a[i,j]:=0; end; procedure afis; var i,j:integer; begin for i:=1 to n do begin for j:=1 to n do write(f,a[i,j]:3); writeln(f); end; writeln(f); end; FUNCTION inside (i,j:integer):boolean; begin inside:=(i in [1..n])and (j in [1..n]) end; procedure back(i,j,pas:integer); var k,inou,jnou:integer; begin a[i,j]:=pas; if pas=n*n then afis else for k:=1 to 8 do begin inou:=i+dx[k]; jnou:=j+dy[k]; if inside(inou,jnou) and (a[inou,jnou]=0) then back(inou,jnou,pas+1); end; a[i,j]:=0; end; begin assign(f,'cal.txt'); rewrite(f); cit; back(1,1,1); close(f); end.

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; } void main() { cin>>n;; back(1,1,1); }

La aceste categorii de probleme se adaug i cele de optim, care presupun alegerea soluiei optime dintre cele generate. De asemenea, problemele de combinatoric se pot rezolva folosind metoda backtracking. Soluiile cerute se pot reprezenta ca vectori de forma X = (x1, ..., xn)S unde S = S1 x ... x Sn, unde

mulimile S1, ...,Sn sunt mulimi finite. Soluiile se genereaz element cu element i trebuie s respecte o serie de reguli, n funcie de problema de generare concret. Algoritmii de tip backtracking prezentai n capitolul anterior vor fi folosii pentru a genera permutri, aranjamente, etc. Pentru fiecare probleme, ns, putem face modificri pentru a crete eficiena algoritmului de rezolvare sau pentru a-l simplifica. Pentru fiecare algoritm vom identifica particularitile sale i condiiile care trebuie puse asupra vectorului soluie. Algoritmii i programele prezentate mai jos folosesc mulimi de forma {1,2,,n} pentru a simplifica lucrurile. Trecerea la o mulime general se face setul de simplu deoarece genernd indicii, practic se genereaz mulimea, i astfel, oricrui vector soluie X generat pe baza indicilor i se poate asocia o soluie dintr-o mulime oarecare. De asemenea, este bine s numrm cte soluii genereaz fiecare program i s verificm aceste numere cu ajutorul formulelor cunoscute de la matematic. Generarea permutrilor Se d o mulime cu n elemente A={a1,a2,,an}. Se cere s se genereze si s se afieze toate permutrile ei. Altfel spus, se cere s se afieze toate modurile n care se pot amesteca elementele mulimii A. Folosim pentru generare mulimea {1,2,,n}. Condiiile care se pun sunt urmtoarele: Fiecare element din vectorul X se ia din {1,2,,n}; Un element Xk este valid dac el nu a fost plasat anterior n vectorul soluie X; Cnd am generat n elemente cu condiiile de mai sus, atunci avem o soluie. Se pot identifica mai multe modaliti de a verifica dac elementul Xk a fost plasat deja n vectorul soluie. Cele mai importante dou sunt: parcurgerea elementelor deja generate pentru a verifica daca Xk apare sau nu ntre ele; folosirea unui vector cu n elemente n care vom avea valori 0 sau 1 corespunztoare elementelor mulimii iniiale. Valoarea 1 va preciza faptul c elementul de pe poziia corespunztoare a fost plasat anterior n vectorul soluie, iar valoarea 0 c nu. Corespunztor acestor dou moduri de a verifica dac un element a mai fost sau nu plasat n vectorul soluie, avem 2 moduri de generare a permutrilor. Generarea aranjamentelor Generm aranjamentele unei mulimi atunci cnd ne se cer toate modurile de a alege m elemente distincte dintre cele n ale mulimii (m<n). Aceast problem se rezolv foarte uor folosind metodele de generarea permutrilor. Singurele modificri presupun citirea numrului m, modificarea condiiei de soluie, care va fi k=m n loc de k=n i a numrului de elemente afiate. Generarea combinrilor Generm combinrilor unei mulimi presupune o condiie suplimentar fa de permutri sau aranjamente. Acest lucru se datoreaz faptului c generarea combinrilor presupune alegerea n ordine strict cresctoare a elementelor care compun vectorul soluie. Astfel, condiia de continuare, sau de validare a unui element este aceea c el trebuie s fie strict mai mare dect cel plasat anterior. n acest mod asigurm faptul c elementele nu se vor repeta i c vor fi generate n ordine strict cresctoare. Trebuie, ns, s avem grij s nu punem aceast condiie si asupra primului element din vectorul soluie, deoarece el nu are cu cine s fie comparat. O optimizare a algoritmului de generare a combinrilor se poate obine pornind instruciunea for pentru plasarea unui element de la valoare urmtoare valorii generate anterior. Trebuie s avem grij la prima poziie, care nu are element anterior. Am putea iniializa X0 cu 0. Astfel nu mai trebuie s verificm dac elementul Xk este mai mare ca Xk-1. Generarea produsului cartezian

Se consider n mulimi A1, A2, ... , An de forma {1,2..,an}. S se genereze produsul cartezian al acestor mulimi. Am considerat mulimile de forma {1,2..,an} pentru a simplifica problema, n special la partea de citire si afiare, algoritmul de generare rmnnd nemodificat. Identificm urmtoarele particulariti i condiii: Fiecare element Xk din vectorul soluie aparine unei mulimi {1,2..,ak}. Aici este o diferen fa de algoritmii anteriori n care fiecare element din soluie era luat din aceeai mulime i trebuie s avem grij la acest fapt cnd scriem programul. Nu exist condiii ntre elementele vectorului soluie. Obinem soluia cnd s-au generat n valori. Generarea submulimilor unei mulimi Generarea submulimilor unei mulimi A cu n elemente se poate face cu ajutorul algoritmului de generare a combinrilor, apelndu-l repetat cu valorile 1, 2, ..., n pentru a genera submulimile cu un element, apoi cele cu dou elemente, apoi cu 3 elemente etc. Aceast modalitate de rezolvare este i mai complicat i mai puin eficient dect urmtoarea, care se bazeaz pe generarea produsului cartezian {0,1}n. Aceast a doua metod este eficient deoarece genereaz 2n soluii, adic exact attea cte submulimi are o mulime cu n elemente. Aadar, generm toate combinaiile de lungime n cu valorile 0 i 1. Pentru fiecare combinaie parcurgem soluia X i afim elementele din mulimea A crora le corespund valori 1 n X. Astfel, pentru combinaia 001011 vom afia elementele de pe poziiile 3, 5 i 6 din mulimea iniial. Generarea partiiilor unei mulimi Generm partiiilor unei mulimi presupune mprirea mulimii n mulimi nevide i disjuncte care reunite s dea ntreaga mulime. Putem, ca i n cazurile anterioare, s considerm mulimea {1,2, ,n}. Construim un vector soluie n care pentru fiecare element vom trece
submulimea n care l vom include. Aceast submulime mai este numit i clas. Algoritmul genereaz pe rnd toate modalitile de a mpri elementele mulimii {1,2,,n} folosind mai nti o singur clas, apoi dou, .a.m.d. pn la n clase.

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.[1][2][3] Exemplul de baz folosit n numeroase manuale de liceu i de nivel universitar este problema reginelor, care cere s se gseasc toate modurile n care pot fi aezate pe o tabl de ah opt regine astfel nct s nu se atace. n abordarea backtracking, candidatele pariale sunt aranjamente de cte k regine pe primele k rnduri ale tablei, toate pe rnduri i coloane diferite. Orice soluie parial ce conine dou regine care se atac poate fi abandonat, deoarece n mod clar restul de regine nu pot fi aezate ntr-o soluie valid. Tehnica backtracking se poate aplica doar pentru probleme ce admit conceptul de candidat parial de soluie i ofer un test relativ rapid asupra posibilitii ca un astfel de candidat s fie completat ctre o soluie valid. Cnd se poate aplica, ns, backtrackingul este adesea mult mai rapid dect cutarea prin metoda forei brute prin toi candidaii, ntruct este capabil s elimine dintr-un singur test un mare numr de candidai. Backtrackingul este util la rezolvarea unor probleme de satisfacere a constrngerilor, cum ar fi cuvintele ncruciate, jocuri de sudoku i alte probleme similare. Ea st la baza unei serii de limbaje de programare logic, cum ar fi Icon, Planner i Prolog. Termenul backtrack a fost inventat de matematicianul american D. H. Lehmer n anii 1950.[4]

Potrebbero piacerti anche