Documente Academic
Documente Profesional
Documente Cultură
Backtraking PDF
Backtraking PDF
1
dac am obinut o soluie complet o afim i se reia algoritmul de
-
la pasul 1.
- dac nu am obinut o soluie, k <----- k+1 si se reia algoritmul de la
pasul 1.
6. Dac nu sunt respectate condiiile de continuare se reia algoritmul de la pasul 2.
7. Dac nu mai exist nici un element neverificat n mulimea Sk nseamn c nu mai
avem nici o posibilitate din acest moment, s construim soluia final aa c
trebuie s modificm alegerile fcute n prealabil, astfel k <----- k-1 i se reia
problema de la pasul 1.
2
v k=1 STIVA
1 i=1
k 1 2 3
v k=2 STIVA
1 1 i=1
k 1 2 3 i=1
element incorect (se repet)
v k=2 STIVA
1 2 i=1,2
k 1 2 3 i=1
v k=3 STIVA
i=1
1 2 1
k 1 2 3 i=1,2
element incorect (se repet) i=1
v k=3 STIVA
1 2 2 i=1,2
k 1 2 3 i=1,2
element incorect (se repet) i=1
v k=3 STIVA
1 2 3 i=1,2,3
k 1 2 3
i=1,2
k=3 s-a obinut o soluie
se nchide ultimul nivel de stiv pentru i=1
c nu mai sunt elemente n ultima
mulime
v k=2 STIVA
i=1,2,3
1 3
i=1
k 1 2 3
STIVA
v k=3
i=1
1 3 1
k 1 2 3 i=1,2,3
element incorect (se repet) i=1
v STIVA
1 3 2 i=1,2
k 1 2 3 i=1,2,3
k=3 i=1
s-a obinut o soluie
STIVA
v k=3 i=1,2,3
1 3 3
i=1,2,3
k 1 2 3
element incorect (se repet) i=1
v k=2
1 3 STIVA
i=1,2,3
k 1 2 3
v k=1 i=1
2
STIVA
k 1 2 3
i=1,2
se repet aceiai pai construindu-se
soluiile urmtoare
3
#include <iostream.h> // PERMUTRI
const MAX=20;
int n,v[MAX] ; //n-nr. de elemente, v[20]-vectorul n care construim soluia
int valid(int k);
int solutie(int k);
void afisare(int k);
void BK(int k);
int main()
{cout<<"n= ";cin>>n; //se citete n
BK(1);
return 0; //apelm funcia BK pentru completarea poziiei 1din vectorul v
}
void BK(int k)
{int i; //i-elementul selectat din multimea Sk, trebuie sa fie variabil local, pentru
// a se memora pe stiv
for (i=1;i<=n;i++) //parcurgem elementele mulimii Sk
{v[k]=i; //selectm un element din mulimea Sk
if (valid(k)) //verificm dac eelementul ales ndeplinete condiiile de continuare
{if (solutie(k)) //verificm dac am obinut o soluie
afisare(k); //se afieaz soluia obinut
else
BK(k+1); //reapemm funcia pentru poziia k+1 din vectorul v
}
}
}
int valid(int k) //verificm condiiile de continuare
{int i;
for (i=1;i<=k-1;i++) //comparm fiecare element din vectorul v cu ultimul element selectat
if (v[i]==v[k]) //deoarece ntr-o permutare elementele nu au voie s se repete,
return 0; //returnm 0 n cazul n care elementul selectat, a mai fost selectat o dat
return 1; //returnm 1 n cazul n care elementul nu mai apare n vector
}
int solutie(int k) //verificm dac am obinut o soluie
{if (k==n) //am obinut o permutare, dac am reuit s depunem n vector n elemente
return 1;
return 0;
}
void afisare(int k) //afieaz coninutul vectorului v
{int i;
for (i=1;i<=k;i++)
cout<<v[i]<<" ";
cout<<endl;
}
Problema generrii permutrilor, este cea mai reprezentativ pentru metoda
backtracking, ea conine toate elementele specifice metodei.
Probleme similare, care solicit determinarea tuturor soluiilor posibile,
necesit doar adaptarea acestui algoritm modificnd fie modalitatea de selecie a
elementelor din mulimea Sk, fie condiiile de continuare fie momentul obinerii unei
soluii.
4
2. PRODUS CARTEZIAN
Se dau n mulimi, ca cele de mai jos:
S1={1,2,3,...,w1}
S2={1,2,3,...,w2}
.........................
Sn={1,2,3,...,wn}
Se cere s se gnereze produsul lor cartezian.
Exemplu:
pemtru n=3 i urmroarele mulimi
S1={1,2} w1=2
S2={1,2,3} w2=3
S3={1,2} w3=2
produsul cartezian este:
S1 xS2 xS3 ={ (1,1,1),(1,1,2),(1,2,1),(1,2,2),(1,3,1),(1,3,2),
(2,2,1),(2,1,2),(2,2,1),(2,2,2),(2,3,1),(2,3,2)}
Prin urmare o soluie este un ir de n elemente, fiecare element iSi, cu i=1,n
S analizm exemplul de mai sus:
1. La pasul k selectm un element din mulimea Sk ={1,2,3,...,wk}.
2. Elementele unei soluii a produsului cartezian, pot s se repete, pot fi n
orice ordine, iar valori strine nu pot apare, deoarece le selectm doar
dintre elementele mulimii Sk . Prin urmare nu trebuie s impunem
condiii de continuare.
3. Obinem o soluie n momentul n care am completat n elemente n vectorul
v.
Vom memora numrul de elemente al fiecerei mulimi Sk , ntr-un vector w. Soluiile
le vom construi pe rnd n vectorul v.
5
void citire() //citirea datelor
{int i;
ifstream f("prod.in");
f>>n; //se citete numrul de mulimi
for(i=1;i<=n;i++)
f>>w[i]; //se citete numrul de elemente al fiecrei mulimi
f.close();
}
int solutie(int k) //funcia soluie determin momentul n care se ajunge la o soluie
{if (k==n) //obinem o soluie dac am dpus n vectorul v, n elemente
return 1;
return 0;
}
void afisare(int k) //afueaz o soluie
{int i;
for (i=1;i<=k;i++)
cout<<v[i]<<" ";
cout<<endl;
}
3. ARANJAMENTE
Se citesc n i p numere naturale cu p<=n. Sa se genereze toate aranjamentle
de n elemente luate cte p.
Exemplu pentru n=3, p=2
(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)
4. COMBINRI
Se citesc n i p numere naturale cu p<=n. S se genereze toate combinrile
de n elemente luate cte p.
Exemplu pentru n=3, p=2. obinem (1,2), (1,3), (2,3)
6
Vom genera pe rnd soluiile problemei n vectorul v=(v1,v2,v3,...,vn), unde vkSk.
S facem urmtoarele observaii:
1. Pentru aceast problem toate mulimile Sk sunt identice, Sk={1,2,3,....,n}.
La pasul k selectm un element din mulimea Sk.
2. n cadrul unei combinri elementele nu au voie s se repete.
S mai observm i faptul c dac la un moment dat am generat de exemplu
soluia (1,2), combinarea (2,1) nu mai poate fi luat n considerare, ea nu mai
reprezint o soluie. Din acest motiv vom considera c elementele vectorului
reprezint o soluie, numai dac se afl n ordine strict cresctoare.
Acestea reprezint condiiile de continuare ale problemei.
3. Oinem o soluie n momentul n care vectorul conine p elemente.
Putem genera toate elementele unei combinri, parcurgnd mulimea {1,2,3,...,n},
apoi s verificm condiiile de continuare aa cum am procedat n cazul permutrilor.
Putem ns mbuntii timpul de execuie, selectnd din mulimea {1,2,3,...,n}, la
pasul k un element care este n mod obligatoriu mai mare dect elementul v[k-1],
adic i=v[k-1]+1.
Ce se ntmpl ns cu primul element plasat n vectorul v?
Acest element a fost plasat pe poziia 1, iar vectorul v deine i elementul v[0] n mod
implicit n C++. v[0]=0, deoarece vectorul v este o variabil global i se iniializeaz
automat elementele lui cu 0.
n acest fel, impunnd aceste restricii nc din momentul seleciei unui element,
condiiile de continuare vor fi respectate i nu mai avem nevoie de funcia valid.
Algoritmul a fost substanial mbuntit, deoarece nu selectm toate
elementele mulimii i nu verificm toate condiiile de continuare, pentru fiecare
element al mulimii.
7
4. SUBMULIMI
S se genereze toate submulimile mulimii S={1,2,3, ... ,n}.
8
Putem construi un algoritm mai eficient pentru generarea tuturor submulimilor
unei mulimi.
De exemplu dac genetm mulimile n urmtoarea ordine:
mulimea vid, {1}, {1,2}, {1,2,3}, {2}, {2,3}, {3}
void main()
{int i;
cout<<"n= ";cin>>n;
cout<<"mulimea vida"<<endl;
BK(1);
}
void BK(int k)
{int i;
for (i=v[k-1]+1;i<=n;i++)
{v[k]=i;
afisare(k);
BK(k+1);
}
}
9
Observm c o dam va fi plasat ntotdeauna singur pe o linie. Acest lucru
ne permite s memorm fiecare soluie ntr-un vector v, considernd c o csut k a
vectorului reprezint linia k iar coninutul ei, adic v[k] va conine numrul coloanei
n care vom plasa regina.
2 4 1 3
1 2 3 4
v[i] v[k]
linia i D
linia k D
3. Obinem o soluie dac am reuit s plasm toate cele n dame, adic k=n.
10
v k=1 D
1
v k=2
1 1
D
v k=2 D
1 2
k=2
1 3
pe linia 3 nu mai putem plasa nici o
dam, selectm alt valoare pe linia 2 D
v k=2 D
1 4
v k=3
1 4 1 D
v k=3 D
1 4 2 D
-pe linia 4 nu putem plasa nici o dam
-pe linia 3 nici o alt coloan nu este
corect
-pe linia 2 nu mai exist nici o poziie
disponibil
-se revine la linia 1
D
v k=1
2
v k=2
2 1
v k=2 D
2 2 D
v k=2
2 3
v k=2
2 4
D
v k=3 D
2 4 1 D
v k=4
2 4 1 1
v k=4 D
D
2 4 1 2
D
v k=4 D
2 4 1 3
11
#include <iostream.h> // DAME
#include <math.h>
#define MAX 20
int n,v[MAX],sol;
void main()
{cout<<"n= ";cin>>n;
BK(1);
}
void BK(int k)
{int i;
for (i=1;i<=n;i++)
{v[k]=i;
if (valid(k)==1)
{if (solutie(k)==1)
sfisare();
else
BK(k+1);
}
}
}
int valid(int k)
{int i;
for (i=1;i<=k-1;i++)
if ((v[i]==v[k])||(abs(v[k]-v[i])==(k-i)))
return 0;
return 1;}
int solutie(int k)
{if (k==n)
return 1;
return 0;}
12
6. Plata unei sume cu monede de valori date.
Fiind dat o sum S i n monede de valori date, s se determine toate modalittile de
plat a sumei S cu aceste monede. Considerm c sunt monede suficiente din
fiecare tip.
Castigul maxim:14
pantaloni 5 5
camasa 10 7
pantofi 5 2
n-numrul de obiecte
G - greutatea maxim admis de rucsac
nume[ ][ ] - reinem renumirea obiectelor
g[ ] - reinem greutatea fiecrui obiect
c[ ] -reinem ctigul pentru fiecare obiect
v[ ] -vectorul soluie:
0-obiectul nu este transportat,
1-obiectul este transportat
14
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#define MAX 20
int n,v[MAX],sol_max[MAX],g[MAX],c[MAX],s,s_max,G,gr,nr_sol;
char nume[MAX][MAX];
void back(int k);
int valid(int k);
void optim();
void citire();
void afisare();
main()
{citire();
back(1);
afisare(); //afisam solutia optima
}
void back(int k)
{ int i;
for(i=0;i<=1;i++)
{v[k]=i; //0-obiectul k sete NEselectat, 1-obiectul k este selectat
if (valid(k))
if (k==n) optim(); //din multimea solutiilor vom retine doar solutia optima
else back(k+1); }
}
int valid(int k)
{ gr=0;
for(int j=1;j<=k;j++)
gr=gr+v[j]*g[j]; //-insumam greutatile obiectelor selectate pana la pasul k
if(gr<=G) return 1 //verificam daca greutatea cumulata nu depaseste greutatea maxima G
else return 0;
}
void optim()
{int s=0; nr_sol++;
for(int j=1;j<=n;j++)
s=s+v[j]*c[j]; //s-calculam suma ctigurilor obiectelor selectate
if((nr_sol==0)||(s>s_max)) //daca s>suma maxima, solutia este mai buna
{s_max=s; //retinem solutia in sol_max
for(j=1;j<=n;j++)
sol_max[j]=v[j];
}
}
void citire()
{ ifstream f("RUCSAC.IN");
f>>n>>G; //n-nr. obiecte, G-greutatea maxima
for (int i=1;i<=n;i++)
f>>nume[i]>>g[i]>>c[i]; //se citeste greutatea si ponderea fiecarui obiect
f.close();
}
void afisare()
{ nr_sol++;
cout<<"Castigul maxim:"<<s_max<<"\n";
for (int j=1;j<=n;j++)
if(sol_max[j]) cout<<nume[j]<<" "<<g[j]<<" "<<c[j]<<endl;
cout<<"\n";
}
15
8.3. Evaluare
TESTUL 1
1. Cnd este necesar ca n rezolvarea unei probleme s aplicm metoda
backtracking?
TESTUL 2
3. S se genereze toate numerele care se pot forma cu cifre aflate n ordine strict
descresctoare, din mulimea {2, 4, 6, 8} .
16
8.4. Probleme propuse
6. n cte moduri se poate ordona mulimea {1,2,..,n} astfel nct fiecare numr
divizibil cu 2, i fiecare numr divizibil cu 3, s aib rangul divizibil cu 2 i
respectiv 3? Afiai toate soluiile.
7. Pentru ntocmirea orarului unei clase de elevi, trebuie s fie programat n fiecare
zi, fie o or de desen din cele dou pe sptmn, fie o ora de fizic din cele
patru pe sptmn. Afiai toate modalitile de ntocmire a orarului.
9. Un elev are n cri de matematic i altul are m cri. n cte moduri pot s
schimbe crile ntre ei, o carte n schimbul alteia? Dar dac schimb dou cri n
schimbul altora 2? Afiai toate soluiile.
10. Fiind dat o hart cu n ri, se cer toate soluiile de colorare a hrii, utiliznd cel
mult 4 culori, astfel nct dou ri cu frontier comun s fie colorate diferit.
17
d. toate turnurile de naltime maxim (far a genera de 2 ori toate turnurile
posibile).
18