Sunteți pe pagina 1din 31

?? ?

?
Backtracking

Spaiul soluiilor
Fie mulimile ,

, o relaie de ordine pe

spaiul soluiilor

funcie de validare

mulimea soluiilor rezultat

funcii de validare parial

se poate aduga un element cu .

Backtracking cutare
complet
lent, costisitoare, complexitate mare
Metod

Verificarea (aproape) tuturor elementelor spa iului solu iilor

,,
- condiii de continuare
se construiete element cu element

primete o valoare din dup ce toate elementele au primit valori


(fie acestea

se trece la elementul
altfel se alege alt valoare pentru
valoarea aleas pentru e consumat mulimea valorilor consumate
dac nu mai snt valori disponibile se revine la elementul anterior
nu garanteaz obinerea unei soluii rezultat

Reprezentare date
ie curent
Configura

Configuraie iniial

Configuraie soluie

Configuraie final

Rezolvare problem:

Configuraie iniial configuraie soluie configuraie soluie configuraie final

Operaii
i avanseaz
Atribuie

ncercare euat

Revenire

Revenirea dup construirea unei soluii

Forma general a algoritmului


ializare
ini

//construire

configuraie iniial

ct timp
//ct timp configuraia nu e final
dac
//configuraie de tip soluie?
reine soluia

//revenire dup construirea unei soluii


altfel
dac
//mai snt valori neconsumate
alege o valoare
dac

altfel

satisfac condiiile de continuare


//atribuie i avanseaz
//revenire

Implementare recursiv
void back(unsigned k)
{
if (k==n) retine_solutie();
else
{
x[k]=init(k);
while (succ(k))
if (continuare(k)) back(k+1);
}
}
retine_solutie - descrie prelucrarea dorit pentru o soluie determinat;
init(k) iniializeaz xk cu o valoare prin care se indic faptul c, pn la acel
moment, nu a fost selectat nici o alternativ pentru poziia k;
succ(k) - calculeaz 1, dac exist succesor pentru xk n Sk (determina i
succesorul)
continuare(k) - calculeaz 1 dac este posibil extinderea drumului curent.

Implementare recursiv

Exemple de probleme care se rezolv prin metoda backtracking:


Generarea tuturor permutrilor.
Problema celor 8 (n) regine.
Generarea tuturor aranjamentelor.
Generarea tuturor prilor unei mulimi (implicit a combinrilor)
Problema canibalilor i a misionarilor
Plata unei sume (cu/fr bancnot unitate).
Problema colorrii hrilor.

Generarea permutrilor
S se genereze toate permutrile mulimii {1, 2,..., n}.

S0 = S2 = ... = Sn-1 = {1, 2,..., n}.


Pentru fiecare k, 0 dac x=(x0, x1,..., xk) este drumul calculat pn la momentul k,
atunci i alternativele posibile pentru starea curent sunt elementele xk+1 din
mulimea {1, 2,..., n} care ndeplinesc .
Exp.: n=3, x1=(1,2,3), x2=(1,3,2), x3=(2,1,3), x4=(2,3,1), x5=(3,1,2), x6=(3,2,1).
init(k) - x[k] 0 (nu a fost selectat nici o valoare pentru x[k]).
succ(k) calculeaz 1 dac x[k] are succesor n mulimea {1, 2,..., n}, caz n care
acesta este determinat prin incrementare. Altfel, funcia calculeaz 0.
continuare(k) returneaz 1 dac i numai dac secvena (x0, x1,..., xk) de la
momentul curent este corect, conform regulilor descrise anterior.
retine_solutie() afieaz soluia calculat la momentul curent

Generarea permutrilor
unsigned x[7], n;
unsigned init()
{
return 0;
}
unsigned succ(unsigned k)
{
return x[k]++<n;
}

unsigned continuare(unsigned k)
{
unsigned i;
for(i=0;(i<k)&&(x[i]-x[k]);i++);
return i==k;
}

Generarea permutrilor
void retine_solutie()
{
for (int i=0;i<n;i++) printf("%u ",x[i]);
printf("\n");
getch();
}

void back(unsigned k)
{
if(k==n) retine_solutie();
else
{
x[k]=init();
while(succ(k))
if(continuare(k))back(k+1);
}
}

Generarea permutrilor
void retine_solutie()
{
for (int i=0;i<n;i++) printf("%u ",x[i]);
printf("\n");
getch();
}

void back(unsigned k)
{
if(k==n) retine_solutie();
else
{
x[k]=init();
while(succ(k))
if(continuare(k))back(k+1);
}
}

Generarea permutrilor
Simplificri n scrierea codului,:
funcia init(k) nu depinde de valoarea lui k i returneaz ntotdeauna
valoarea 0;
funcia succ(k) nu depinde de valoarea parametrului k i realizeaz
ntotdeauna o incrementare (S0 = S1 = ... =Sn-1 = {1, 2,..., n}).
void back(unsigned k)
{
unsigned i;
if (k==n) retine_solutie();
else
for (i=1;i<=n;i++)
{
x[k]=i;
if (continuare(k))back(k+1);
}
}

nlocuirea structurii repetitive while cu ciclul for este posibil datorit faptului
c funcia succ realiza incrementarea valorii elementului x[k].

Problema celor 8 regine

- coloana pe care se afl dama de pe linia i

Din aceast reprezentare rezult c dou regine


nu pot fi plasate pe aceeai linie a tablei de ah.
Funcia is_ok(k) (continuare din forma general)
calculeaz 1 dac,la adugarea reginei k,
configuraia rezultat este corect, adic:
conf[k]<>conf[i]

conf k conf i k i

(reginele de pe liniile i i k sunt plasate pe diagonale diferite).


Funciaa regine implementeaz metoda backtracking pentru rezolvarea problemei.

Problema celor 8 regine


// Funcia care verific posibilitatea adugrii reginei k
unsigned is_ok(unsigned k)
{
for(unsigned i=0;i<k;i++)
if ((conf[k]==conf[i])||
(abs(conf[k]-conf[i])==abs(k-i)))
return 0;
return 1;
}
// Retine o configuratie (afisare)
void retine_solutie()
{
printf("Configuratie corecta:\n");
for(int i=0;i<n;i++){
printf("Regina %i se afla pe ",i+1);
printf("Linia:%i si coloana%u\n",i+1,conf[i]);
}
printf("\n");getch();
}

Problema celor 8 regine


// Rezolvarea problemei prin backtracking
// varianta recursiva
void regine(unsigned i)
{
if(i==n){
retine_solutie ();
nr++;}
else
for(unsigned k=1;k<n+1;k++){
conf[i]=k;
if(is_ok(i)) regine(i+1);
}
}

Generarea tuturor aranjamentelor


Problem. S se genereze toate secvenele de cte p componente, dou cte
dou distincte, din mulimea {1,2,..., n}, n 7, p n dat.
Determinarea unei soluii are loc atunci cnd k devine p (s-a generat o
secven de p elemente, dou cte dou distincte, din mulimea {1,2,..., n}).

unsigned x[7],n,p;
unsigned init()
{return 0;}
unsigned succ(unsigned k)
{return x[k]++<n;}
unsigned continuare(unsigned k)
{
unsigned i;
for(i=0;(i<k)&&(x[i]-x[k]);i++);
return i==k;
}

Generarea tuturor aranjamentelor

void retine_solutie()
{
for (int i=0;i<p;i++) printf("%u ",x[i]);
printf("\n");getch();
}

void back(unsigned k)
{
if(k==p) retine_solutie();
else
{
x[k]=init();
while(succ(k))
if(continuare(k))back(k+1);
}
}

Generarea tuturor prilor unei


mulimi
Problem. S se scrie programul C pentru generarea tuturor submulimilor
mulimii S={1, 2,..., n}, n 7.
Vor fi generate succesiv toate submulimile cu k elemente, k=1, 2,, n.
Fiecare submulime SubS este reprezentat prin funcia indicator:

0, S[i] SubS
SubS[i]=
1, altfel

Generarea unei soluii (submulime cu k elemente) este realizat cnd suma


componentelor vectorului SubS este k.
Fiecare submulime generat este memorat ntr-un vector de lungime 2n,
care, n final, va reprezenta P({1, 2,..., n}).

Generarea tuturor prilor unei


mulimi
int n; long nr; int x[10]; int tot[1024][10];
// Funcia care verific posibilitatea de a continua
int suma(int t,int k)
{
int s,i;
for(s=i=0;i<=t;i++)s+=x[i];
return s<=k;
}
// Funcia care calculeaz suma elementelor vectorului construit
int sumaf()
{
int s,i;
for(s=i=0;i<n;i++)s+=x[i];
return s;
}

Generarea tuturor prilor unei


mulimi
void back(int k,int t)
{
int i;
if (t==n)
if(sumaf()==k){ // Dac a fost generat o submulime cu k
elemente
for(i=0;i<n;i++)
tot[nr][i]=x[i]; // Copierea submulii n vectorul P({1, 2,..., n}).
nr++;
}
else ;
else
for(i=2;i>=1;i--)
{
x[t]=i-1; // Variantele posibile pentru poziia i sunt 1 sau 0
if(suma(t,k)) back(k,t+1);
}
}

Problema canibalilor i a
misionarilor

Problem. Se presupune c pe malul unui ru se afl o barc, trei misionari i


trei canibali parial educai. Misionarii i canibalii doresc s traverseze rul,
dar barca nu poate transporta dect cel mult dou persoane. Deoarece
canibalii sunt numai parial educai, nu se poate avea ncredere n ei, aa c
trebuie ca, n orice moment, pe cele dou maluri, numrul misionarilor s fie
cel puin egal cu cel al canibalilor. S se scrie un program pentru rezolvarea
problemei, indicndu-se, la fiecare moment, numrul misionarilor i al
canibalilor pe fiecare dintre maluri i poziia brcii.

typedef struct{
int ncs,ncd,nms,nmd; //nr. de canibali si misionari de pe malurile
stang si drept ale raului
int pb; // pozitia barcii
}stare;

stare sol[50];

Problema canibalilor i a
misionarilor
int mut[2][5]={{0,1,1,2,0},{1,0,1,0,2}}; // (mut[0][i],mut[1][i])-o
posibilitate corect de a alege
// mut[0][i] canibali i mut[1][i] misionari pentru a ndeplini condiia
de non-atac la o mutare
FILE *f; // Fisierul in care prezint solutiile problemei
// Funcia verific dac starea st a fost deja trecuta in vectorul solutie
unsigned visit(stare st,int l)
{
// 1- starea st a fost trecuta anterior in solutie, 0- in caz contrar
for(int i=0;i<l;i++)
if ((sol[i].ncs==st.ncs) &&(sol[i].ncd==st.ncd) &&
(sol[i].nmd==st.nmd) &&(sol[i].nms==st.nms) &&
(sol[i].pb==st.pb))
return 1;
return 0;
}

Problema canibalilor i a
misionarilor
// Funcia verific dac starea st este o stare valid (respect condiiile
problemei)
unsigned pot_muta(stare st, int j)
{
// 1- starea st poate fi acceptata
// 0- in caz contrar
if (st.pb==-1) // barca este pe malul stng
if((st.ncs>=mut[0][j]) &&
// pot selecta mut[0][j] canibali i
mut[1][j] misionari
(st.nms>=mut[1][j]))
return 1;
if (st.pb==1) // barca este pe malul drept
if((st.ncd>=mut[0][j])&&(st.nmd>=mut[1][j]))
return 1;
return 0;
}

Problema canibalilor i a
misionarilor
void back(stare st, int l)
{
stare st1; int i,j; st=sol[l];
if((st.ncd+st.nmd==6)&&(st.pb==1)){// o poziie valid
for(i=0;i<=l;i++){
fprintf(f,"Mal st.: canibali="); fprintf(f,"%u",sol[i].ncs);
fprintf(f,", misionari="); fprintf(f,"%u",sol[i].nms);
fprintf(f," Mal dr.: canibali="); fprintf(f,"%u",sol[i].ncd);
fprintf(f,", misionari="); fprintf(f,"%u",sol[i].nmd);
fprintf(f," barca pe malul ");
if (sol[i].pb==-1) fprintf(f,"stang\n");
else fprintf(f,"drept\n");
}
fprintf(f,"\n");
}

Problema canibalilor i a
misionarilor
else
for (j=0;j<5;j++) // pentru toate cele 5 posibiliti de alegere a unei
mutri
if(((st.ncs+st.pb*mut[0][j]<=st.nms+st.pb*mut[1][j]) ||
(st.nms+st.pb*mut[1][j]==0)) &&
// dac nr. canibali rmai pe malul stng<= nr. misionari rmai pe
malul stng
//sau nr. misionari rmai pe malul stng =0
((st.ncd-st.pb*mut[0][j]<=st.nmd-st.pb*mut[1][j]) || (st.nmdst.pb*mut[1][j]==0)) &&
(st.nms+st.pb*mut[1][j]>=0) &&
//dac nr. misionari rmai pe malul stng este nenegativ
(st.ncs+st.pb*mut[0][j]>=0) &&
(st.nmd-st.pb*mut[1][j]>=0) && (st.ncd-st.pb*mut[0][j]>=0)
&&pot_muta(st,j)){
st1=st;
st1.ncs+=st1.pb*mut[0][j];
st1.nms+=st1.pb*mut[1][j];
st1.nmd-=st1.pb*mut[1][j];
st1.ncd-=st1.pb*mut[0][j];
st1.pb=-st1.pb;

Problema canibalilor i a
misionarilor
Mal stng
Mal drept

Mal st.: canibali=3 , misionari=3


malul stang
Mal st.: canibali=2 , misionari=2
malul drept
Mal st.: canibali=2 , misionari=3
malul stang
Mal st.: canibali=0 , misionari=3
malul drept
Mal st.: canibali=1 , misionari=3
malul stang
Mal st.: canibali=1 , misionari=1
malul drept
Mal st.: canibali=2 , misionari=2
malul stang
Mal st.: canibali=2 , misionari=0
malul drept
Mal st.: canibali=3 , misionari=0
malul stang
Mal st.: canibali=1 , misionari=0

Poziie barc
Mal dr.: canibali=0 , misionari=0 barca pe
Mal dr.: canibali=1 , misionari=1 barca pe
Mal dr.: canibali=1 , misionari=0 barca pe
Mal dr.: canibali=3 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=2 barca pe
Mal dr.: canibali=1 , misionari=1 barca pe
Mal dr.: canibali=1 , misionari=3 barca pe
Mal dr.: canibali=0 , misionari=3 barca pe
Mal dr.: canibali=2 , misionari=3 barca pe

Problema canibalilor i a
misionarilor
Mal stng
Mal drept

Mal st.: canibali=3 , misionari=3


malul stang
Mal st.: canibali=2 , misionari=2
malul drept
Mal st.: canibali=2 , misionari=3
malul stang
Mal st.: canibali=0 , misionari=3
malul drept
Mal st.: canibali=1 , misionari=3
malul stang
Mal st.: canibali=1 , misionari=1
malul drept
Mal st.: canibali=2 , misionari=2
malul stang
Mal st.: canibali=2 , misionari=0
malul drept
Mal st.: canibali=3 , misionari=0
malul stang
Mal st.: canibali=1 , misionari=0

Poziie barc
Mal dr.: canibali=0 , misionari=0 barca pe
Mal dr.: canibali=1 , misionari=1 barca pe
Mal dr.: canibali=1 , misionari=0 barca pe
Mal dr.: canibali=3 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=2 barca pe
Mal dr.: canibali=1 , misionari=1 barca pe
Mal dr.: canibali=1 , misionari=3 barca pe
Mal dr.: canibali=0 , misionari=3 barca pe
Mal dr.: canibali=2 , misionari=3 barca pe

Problema canibalilor i a
misionarilor
Mal stng
Mal drept

Mal st.: canibali=3 , misionari=3


malul stang
Mal st.: canibali=1 , misionari=3
malul drept
Mal st.: canibali=2 , misionari=3
malul stang
Mal st.: canibali=0 , misionari=3
malul drept
Mal st.: canibali=1 , misionari=3
malul stang
Mal st.: canibali=1 , misionari=1
malul drept
Mal st.: canibali=2 , misionari=2
malul stang
Mal st.: canibali=2 , misionari=0
malul drept
Mal st.: canibali=3 , misionari=0
malul stang
Mal st.: canibali=1 , misionari=0

Poziie barc
Mal dr.: canibali=0 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=0 barca pe
Mal dr.: canibali=1 , misionari=0 barca pe
Mal dr.: canibali=3 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=2 barca pe
Mal dr.: canibali=1 , misionari=1 barca pe
Mal dr.: canibali=1 , misionari=3 barca pe
Mal dr.: canibali=0 , misionari=3 barca pe
Mal dr.: canibali=2 , misionari=3 barca pe

Problema canibalilor i a
misionarilor
Mal stng
Mal drept

Mal st.: canibali=3 , misionari=3


malul stang
Mal st.: canibali=1 , misionari=3
malul drept
Mal st.: canibali=2 , misionari=3
malul stang
Mal st.: canibali=0 , misionari=3
malul drept
Mal st.: canibali=1 , misionari=3
malul stang
Mal st.: canibali=1 , misionari=1
malul drept
Mal st.: canibali=2 , misionari=2
malul stang
Mal st.: canibali=2 , misionari=0
malul drept
Mal st.: canibali=3 , misionari=0
malul stang
Mal st.: canibali=1 , misionari=0

Poziie barc
Mal dr.: canibali=0 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=0 barca pe
Mal dr.: canibali=1 , misionari=0 barca pe
Mal dr.: canibali=3 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=0 barca pe
Mal dr.: canibali=2 , misionari=2 barca pe
Mal dr.: canibali=1 , misionari=1 barca pe
Mal dr.: canibali=1 , misionari=3 barca pe
Mal dr.: canibali=0 , misionari=3 barca pe
Mal dr.: canibali=2 , misionari=3 barca pe

Spor la nvat!

S-ar putea să vă placă și