Documente Academic
Documente Profesional
Documente Cultură
Metoda Backtracking
1.
2.
3.
4.
5.
6.
7.
8.
9.
Aspecte teoretice
Exemplu pentru nelegerea metodei
Permutri
Aranjamente
Combinri
Problema celor n dame
Problema colorrii hrilor
Problema comis voiajorului
Problema plaii unei sume s utiliznd m tipuri de
monede
10. Backtracking recursiv
11. Aranjamente si permutari rezolvate recursiv
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
O metod simpl de a genera soluiile rezultat const n a
genera ntr-un mod oarecare toate soluiile posibile i de a alege
dintre acestea doar pe cele care verific condiiile interne.
Dezavantajul const n faptul c timpul cerut este foarte mare.
etajul
etajul
etajul
etajul
etajul
1
2
3
4
5
are
are
are
are
are
5 etaje
10
10
10
10
10
raioane
raioane
raioane
raioane
raioane
cu
cu
cu
cu
cu
pantofi
ciorapi
pantaloni
cmi
cravate
Cum se procedeaz:
Construirea
tipului sir
#include<iostream>
#include<stdio.h>
using namespace std;
typedef int sir[100];
sir x;
int k, as,ev;
Realizarea funciei
valid
void valid(int&ev)
{
ev=1;
}
Am gsit ce mi place
Programul principal
int main(void)
{
k=1;
x[k]=0;
while(k>0)
{
do
Afiarea rezultatulu
if(as)
if(k==5)
afis(x,k);
else
{
k=k+1;
succ(x,k,as);
if (as)
x[k]=0;
valid(ev);
}
while(as && !ev);
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)
3.
Dac la fiecare etaj numrul de magazine este variabil (nu 10)
condiia de testare din funcia succesor este
if(x[k]<n[k])
Atunci cnd nu exist condiii ntre componentele
vectorului soluie funcia valid are forma:
void valid(int&ev)
{
ev=1;
}
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;
void succ(sir x, int k, int &as)
{
if(x[k]<m)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}
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
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;
}
}
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);
}