Documente Academic
Documente Profesional
Documente Cultură
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Aspecte teoretice
Exemplu pentru nelegerea metodei
Permutri
Aranjamente
Combinri
Problema celor n dame
Problema colorrii hrilor
Problema comis voiajorului
Problema pla
ii unei sume s utiliznd m tipuri de monede
Backtracking recursiv
Aranjamente si permutari rezolvate recursiv
Metoda Backtracking
1. Aspecte teoretice
Metoda Backtracking este o metod de elaborare a
algoritmilor. Ea se aplic problemelor n care soluia se
poate reprezenta sub forma unui vector, X=(x1,x2,...xm),
care aparine lui S=S1xS2x...Sm
- S=S1xS2x...Sm se numete spaiul soluiilor
posibile
- Pentru fiecare problem n parte se dau anumite
condiii ntre componentele vectorului soluie care se
numesc condiii interne
- Soluiile posibile care verific condiiile interne se
numesc soluii rezultat
- Metoda Backtracking i propune s genereze toate
soluiile rezultat
2. Exemplu pentru
nelegerea metodei
Pentru a nelege mai uor prezentm urmtorul
exemplu:
Presupunem c dorim s ne mbrcm de la un
magazin pentru o festivitate i dorim s cumprm:
pantofi, ciorapi, pantaloni, cma i cravata astfel
nct acestea s se asorteze ntre ele, s se genereze
toate modalitile de a ne mbrca.
Magazinul are:
5 etaje
La etajul 1 are 10
La etajul 2 are 10
La etajul 3 are 10
La etajul 4 are 10
La etajul 5 are 10
raioane
raioane
raioane
raioane
raioane
cu
cu
cu
cu
cu
pantofi
ciorapi
pantaloni
cmi
cravate
Cum se procedeaz:
Cum se realizeaz
afiarea
pentru i de la 1 la k
se afieaz x[i]
cursorul trece la linia urmtoare
int k, as,ev;
Am gsit ce mi place
int main(void)
{
k=1;
x[k]=0;
while(k>0)
{
do
{
succ(x,k,as);
if (as)
valid(ev);
}
while(as&&!ev);
if(as)
if(k==5)
afis(x,k);
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
}
Comentarii
1.
Dac
la etajul 1 ar fi fost n1
raioane
la etajul 2 ar fi fost n2
raioane
.......
la etajul k ar fi fost nk
raioane
Funcia succesor se
modific astfel:
Comentarii
2.
Dac magazinul are m etaje atunci condiia
dac s-au fcut toate cumprturile sau
s-a ajuns la ultimul etaj se scrie
if(k==m)
Comentarii
3.
Dac la fiecare etaj numrul de
magazine este variabil (nu 10)
condiia de testare din funcia
succesor este
if(x[k]<n[k])
Permutri
O permutare a unei mulimi cu n elemente este un ir
de
elemente
obinut
prin
schimbarea
ordinii
elementelor mulimii date sau chiar mulimea nsi.
Ne gndim la generarea permutrilor atunci cnd se d
o mulime cu n elemente ca date de intrare iar soluia
este sub forma de vector, tot cu n elemente, ale crui
componente sunt distincte i aparin mulimii date.
Exemplu: Fie A={1,2,3}. Permutrile mulimii A sunt:
(1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1).
Fie A={a1, a2,,am} o mulime cu elemente de tip
ntreg. Trebuie determinate elementele mulimii { y1, y2,
,ym }| ykA, k=1,2,...,m, pentru yiyj pentru ij}.
Deci, x=( x1, x2,,xm) unde x{1,...,m}, elementele
vectorului x trebuie s fie distincte.
Programul:
#include<iostream.h>
#include<stdio.h>
typedef int sir[100];
sir x;
int i,k,m;
int as,ev;
sir a;
int main(void)
{
cout<<"m=";
cin>>m;
for(i=1;i<=m;i++)
cin>>a[i];
k=1;
x[k]=0;
while(k>0)
{
do
{
succ(x,k,as);
if(as) valid(x,k,ev);
}
while(as&&!ev);
if(as)
if(k==m) afis(x,k);
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
}
Aranjamente
Se dau dou mulimi A={1,2,,p} i
B={1,2,,m} se cer toate funciile
injective definite pe A cu valori n B. O
astfel de problem este una de generare a
aranjamentelor de n luate cate p (Anp).
Exemplu: p=2, n=3. Avem (1,2), (2,1),
(1,3), (3,1), (2,3), (3,2). De exemplu (2,1)
este funcia f:AB dat astfel f(1)=2,
f(2)=1. Avem relaiile: =m(m-1)...(m-p+1).
Avem relaiile:
m!
A
(m p )
p
n
= m(m-1)...(m-p+1).
#include<iostream.h
>
#include<stdio.h>
typedef int sir[100];
sir x;
int i,k,m,p;
int as,ev;
sir a;
se verific dac
xkxi unde
int main(void)
{
cout<<"m=";
cin>>m;
for(i=1;i<=m;i++)
cin>>a[i];
cout<<"p=";
cin>>p;
k=1;
x[k]=0;
while(k>0)
{
do
{
succ(x,k,as);
if(as) valid(x,k,ev);
}
while(as&&!ev);
if(as)
if(k==p) afis(x,k);
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
}
Combinri
Fiind dat o mulime A cu n elemente, a combina
elementele mulimii n grupe de cte p<n
elemente nseamn a determina toi vectorii cu p
elemente ale cror componente aparin mulimii A
i sunt sortate cresctor.
Ne gndim la generarea combinrilor atunci
cnd se d o mulime cu n elemente ca date de
intrare iar soluia este sub forma unui vector cu
p<n elemente, astfel nct s nu aib importan
ordinea pe care o au n cadrul irului.
Componentele sunt sortate cresctor i aparin
mulimii date.
Fie A={1,2,3}. Combinrile mulimii A n grupe
de cte dou elemente sunt (1,2), (1,3), (2,3).
#include<iostrea
m.h>
#include<stdio.h
>
typedef int
sir[100];
sir x;
int i,k,m,p;
int as,ev;
sir a;
se verific dac
componentele aparin
mulimii date i sunt
int main(void)
{
cout<<"m=";
cin>>m;
for(i=1;i<=m;i++)
cin>>a[i];
cout<<"p=";
cin>>p;
k=1;
x[k]=0;
while(k>0)
{
do
{
succ(x,k,as);
if(as) valid(x,k,ev);
}
while(as&&!ev);
if(as)
if(k==p) afis(x,k);
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
}
k
i
xi
xk
k
i
xk
xi
Dama
k i dama i se gsesc pe
aceeai diagonal dac k-i=|xk-xi|
Dama
k i dama i se gsesc pe
aceeai coloan dac xk=xi.
Dama
k i dama i nu se afl e
aceeai lunie niciodat datorit
modului de construire a vectorului x
int main(void)
{
cout<<"n=";
cin>>n;
k=1;
x[k]=0;
while(k>0)
{
do
{
succ(x,k,as);
if(as)
valid(x,k,ev);
}
while(as&&!ev);
if(as)
if(k==n) afis(x,k);
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
}
Problema colorrii
hrilor
Fiind dat o hart cu n tri, se cer toate
modalitile de colorare a hrii, utiliznd cel mult m
culori, astfel nct dou ri cu frontier comun s
fie colorare diferit. Este demonstrat faptul c sunt
suficiente numai 4 culori ca orice hart s poat fi
colorat.
Pentru rezolvare se vor folosi:
k: variabil ntreag, care reprezint o ar
x: vector cu componente ntregi cu proprietatea x k
reprezint culoarea rii cu numrul k
deoarece sunt n ri i m culori, k={1,...,n} i
xk={1,...,m}
x=(x1,x2,...,xn) unde xk{1,...,n}.
3
2
5
0 1 0 1 1
1 0 0 1 1
A 0 0 0 1 1
1 1 1 0 1
1 1 1 1 0
Concluzie:
ara k i ara i sunt vecine, dac (a i,k=1) sau
(ak,i=1)
ara k i ara i au aceeai culoare dac x k=xi
Comentarii la funcia valid:
Trebuie verificat dac ara k i ara i ce sunt
ri vecine au culori diferite, adic dac
ak,i=1 pentru xkxi, pentru i=1...k-1.
#include<iostream.h>
#include<math.h>
typedef int sir[100];
sir x;
int m,i,k,n,j;
int as,ev;
int a[100][100];
int main(void)
{
cout<<"Dati numarul de
tari:";
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>a[i][j];
a[j]
[i]=a[i][j];
}
k=1;
x[k]=0;
while(k>0)
{
do
{
succ(x,k,as);
if(as) valid(x,k,ev);
}
while(as&&!ev);
if(as)
if(k==n) afis(x,k);
else
{
k=k+1; x[k]=0;
}
else k=k-1;
}
}
Problema comis
voiajorului
Un comis voiajor trebuie s viziteze un
numr de n orae. Iniial acesta se afl ntrunul din ele, notat 1. Comis voiajorul
dorete s nu treac de dou ori prin
acelai ora iar la ntoarcere s revin n
oraul 1. Cunoscnd legturile existente
ntre orae, se cere s se tipreasc toate
drumurile posibile pe care le poate efectua
comis voiajorul.
matricea de
adiacen este:
1
A 0
1
1
1
0
0
1
1
0
0
0
1
1
1
1
1
0
0
1
1
Concluzii:
ntre oraele k i i exist drum dac ak,i=1
i (ai,k=1), deci ntre oraele xk i xi exist
drum dac a[xk][xi]=1 (i a[xi][xk]=1)
oraul xk trebuie s fie diferit de oraul xi
pentru i=1...k-1
oraul xn trebuie s fie vecin cu oraul x1
adic a[xk][x1]=1
Programul
#include<iostream.h>
#include<math.h>
typedef int sir[100];
sir x;
int i,j,k,n,as,ev;
int a[100][100];
int main(void)
{
cout<<"Dati numarul de orase:";
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
cin>>a[i][j];
a[j][i]=a[i][j];
}
x[1]=1;
k=2;
x[k]=1;
while(k>1)
{
do
{
succ(x,k,as);
if(as) valid(x,k,ev);
}
while(as&&!ev);
if(as)
if(k==n) afis(x,k);
else
{
k=k+1;
x[k]=1;
}
else k=k-1;
}
}
2
2
4
5
4
5
3
3
3
3
5
4
5
4
2
2
......................................................
S
xk poate lua valori ntre 0 i n ka=
.......................................................
S
xm poate lua valori ntre 0 i nm a=
nm
n2
nm-1
n1
1
xk
nk
Programul
#include<iostream.h>
typedef int sir[100];
sir x,n,a;
int m,i,k,S,as,ev;
int main(void)
{
cout<<"Dati valoarea sumei:"; cin>>S;
cout<<"Dati numarul monedelor m="; cin>>m;
cout<<"Dati valorile celor "<<m<<" monede: ";
for(i=1;i<=m;i++)
{
cin>>a[i];
n[i]=S/a[i];
}
k=1;
x[k]=-1;
while(k>0)
{
do
{
succ(x,k,as);
if(as) valid(ev);
}
while(as&&!ev);
if(as)
if(k==m) afis(x,k);
else
{
k=k+1;
x[k]=-1;
}
else k=k-1;
}
}
Bactracking recursiv
void back(int k)
{
if(solutie(k)) afis(x,k);
else
{
x[k]=0;
while(succ(x,k))
{
valid(x,k,ev)
if(ev)
back(k+1);
}
}
}
Permutri recursiv
funcia succ
#include<iostream.h>
typedef int sir[100];
sir x;
int i,k,n,ev;
int succ(sir x, int k)
{
if(x[k]<n)
{
x[k]=x[k]+1;
return 1;
}
else return 0;
}
funcia back
void back(int k)
{
if (k==n+1) afis(x,k);
else
{
x[k]=0;
while(succ(x,k))
{
valid(x,k,ev);
if(ev)
back(k+1);
}
}
}
programul principal
int main(void)
{
cout<<"n=";
cin>>n;
back(1);
}
Aranjamente - recursiv
#include<iostream.h>
typedef int sir[100];
sir x;
int i,k,n,ev,m;
int succ(sir x, int k)
{
if(x[k]<n)
{
x[k]=x[k]+1;
return 1;
}
else return 0;
}
Funcia back
void back(int k)
{
if (k==m+1) afis(x,k);
else
{
x[k]=0;
while(succ(x,k))
{
valid(x,k,ev);
if(ev)
back(k+1);
}
}
}
programul principal
int main(void)
{
cout<<"n=";
cin>>n;
cout<<"m=";
cin>>m;
back(1);
}