Sunteți pe pagina 1din 23

Tehnicide program are

D rago G oia

Prezentare
met

ode backtra
cking

g
n
i
k
c
a
r
t
k
c
a
b
p
r
o
C

Probleme cu backtracking

Metode backtracking
Prezentare metod general
Implementare it

erativ

v
i
s
r
u
c
e
r
e
r
a
t
n
e
Implem

In plan

Metoda
general

Este o metod general de


programare, i poate fi adapt
pentru orice
problem pentru care dorim s
obinem toate soluiile posibile,
sau s selectm o
soluie optim, din mulimea
soluiilor posibile.
Backtracking este ns i cea mai
costisitoare metod din punct de
vedere
al timpului de execuie.2
- dac am obinut o soluie
complet o afim i se reia
algoritmul de la pasul 1.

void BK(int k) //k-poziia din vector care se completeaz

Implementare recursiv
Implementarea recursiv a
algoritmului furnizat de metoda
backtracking, este mai natural i deci
mai uoar.
Segmentul de stiv pus la dispoziie
prin apelul funciei este gestionat n
mod automat de sistem.
Revenirea la pasul precedent se
realizeaz n mod natural prin
nchiderea nivelului de stiv.

Continuare

{int i;
for (i=1; i<=nr_elemente_Sk; i++) //parcurge elementele
mulimii Sk
{ v[k]=i; //selecteaz un element din mulime
if (validare(k)==1) //valideaz condiiile de continuare ale
problemei
{ if (solutie(k)==1) //verific dac s-a obinut o soluie
afisare(k); //afieaz soluia
else
BK(k+1); //reapeleaz functia pentru poziia k+1
}
} //dac nu mai exist nici un element neselectat n
mulimea Sk,
} //se nchide nivelul de stiv i astfel se revine pe poziia
k-1 a
//vectorului

Implementare iterativa
1. Fiecare nivel al stivei trebuie iniializat cu o valoare aflat
naintea tuturor valorilor posibile din mulimea soluiilor. Aceast
afiare se face cu funcia init().
2. Gsirea urmtorului element netestat de pe un nivel k al stivei
St se face cu funcia
succesor (), altfel 1, dac exist valoare netestat pentru nivelul k
. Dac exist valoare netestat
(succesor), atunci se va alege o nou valoare (netestat) pentru
nivelul k.
3. Odat ales un element testarea condiiilor de validare se face cu
funcia
valid() 0, altfel 1, dac valoarea de p enivelul k ndeplinet e
condiondide validare
4. Testul dac s-a ajuns sau nu la o soluie final se face cu funcia
soluie ( ) 0, altfel 1, dac s- a completat ultimul nivel din stiv
5. Soluia se tiprete cu funcia tipar()

void bkt()
{k=1; //se completeaz stiva ncepnd cu primul nivel
init (); //se iniializeaz primul nivel al stivei
while (k>0)
{do{AS= succesor(); }while (AS && valid()==0);
//se caut succesor pe nivelul k atta timp ct exist
succesor care nu este valid
if (AS) //exist succesor
if solutie() //dac s-a completat stiva
tipar() //se tiprete soluia
else //stiva nu s-a completat
{ k++; // se trece pe nivelul urmtor
init(); // se iniializeaz noul nivel }
else k--; // nu exist succesor pentru nivelul k,
deci se coboar un nivel n stiv }}

n general vom modela soluia problemei ca un vector v=(v1,v2,v3,...,vn) n care


fiecare element vk aparine unei mulimi finite i ordonate Sk, cu k=1,n. n anumite
cazuri particulare, mulimile S1 ,S2, S3,...,Sn pot fi identice . Procedm astfel:
1. La fiecare pas k pornim de la o soluie parial v=( v1,v2,v3,...,vk-1) determinat
pn n acel moment i ncercm s extindem aceast soluie adugnd un nou
element la sfritul vectorului.
2. Cutm n mulimea Sk , un nou element.
3. Dac exist un element neselectat nc, verificm dac acest element
ndeplinete condiiile impuse de problem, numite condiii de continuare.
4. Dac sunt respectate condiiile de continuare, adugm elementul soluiei
pariale.
5. Verificm dac am obinut o soluie complet.
Backtracking este o metod de parcurgere sistematic a spaiului
soluiilor posibile al unei probleme.
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.

Paii

Backtracking este o metod de parcurgere


sistematic a spaiului
soluiilor posibile al unei probleme.
Este o metod general de programare, i
poate fi adapt pentru orice
problem pentru care dorim s obinem toate
soluiile posibile, sau s selectm o
soluie optim, din mulimea soluiilor posibile.
Backtracking este ns i cea mai costisitoare
metod din punct de vedere
al timpului de execuie.

Probleme generale

Info plus

Backtracking recursiv

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

Algoritm

Recursiv

Permutri
S se genereze toate permutrile primelor n numere
naturale.
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. ntruct n cadrul unei permutri elementele nu au
voie s se repete

Exemplu pentru n=3 S1= S2=


S3={1,2,3}
(1,2,3) (1,3,2) (2,1,3) (2,3,1) (3,1,2)
(3,2,1)

aceast condiie reprezent condiia de continuare a


problemei.
3. Obinem o soluie n momentul n care completm
vectorul cu n elemente.

Recursiv

Cu backtracking

Fr backtracking

Recursiv

Timpii de executie

Timpii de executie
Permutari cu backtracking

Permutari far backtracking

Asemenea cum se poate deduce din


timpul de execuie, n aceast poz
ne este exemplificat gradul
exponenial de complexitate al
metodei backtracking.

Recursiv

Probleme generale
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.

01
Teorie

03
02
Exemplu Rezolvare

Backtracking n 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;

Continuare

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).

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++;

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:

a[x][y]=2;

d[k].x=x;

if((x<1)||(x>m)||(y<1)||(y>n))

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-1,y);

ies(x,y-1); }

ies(x,y+1);

ies(x+1,y);

ies(x,y-1);

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:

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}}

solutia 2
Fie urmatorul labirint: m=6 n=10 Li=4, Ci=3

(4,3) (4,4) (4,5) (4,6) (4,7) (4,8) (4,9) (4,10) (4,11)

1111011111
1111011111
1111011111
1100000000
1111111011
1111111011

1111011111
1111011111
1111011111
1122222222
1111111011
1111111011

Exemplu

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 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

for(int i=1;i<=k;i++)

Sursa

cout<<"("<<d[i].x<<','<<d[i].y<<") ";

#include<fstream>

afis_mat();

#include<conio.h>

getch();

using namespace std;

struct pozitie

{int x,y;};

cout<<endl;}
void ies(int x,int y) //genereaza drumul
{if(a[x][y]==0)

int a[20][20];//labirintul

{k++;

int k,n,m,Li,Ci,nr_sol;

a[x][y]=2;

pozitie d[50];

d[k].x=x;

void afis_mat() //afiseaza matricea

d[k].y=y;

{cout<<endl;

if((x<1)||(x>m)||(y<1)||(y>n))

for(int i=1;i<=m;i++)

{for(int j=1;j<=n;j++)

cout<<a[i][j]<<" ";

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";
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}
Int main( ){

int main()
{clrscr();
k=0;
citire();
ies(Li,Ci);
afis_mat();
getch(); }

Subprograme folosite
Metoda backtracking va folosi o serie
de proceduri i funcii care vor fi
folosite totdeauna cu acelai nume i
aceiai parametri:
procedure init(k, st);
procedure succesor(k, st, as);
procedure validare(k, st, ev);
function solutie(k): boolean;
procedure tipar;

procedure init(k, st);


Rol: atribuie elementului situat pe nivelul k
o valoare iniial
Parametri: k - nivelul in stiv,st - stiv

procedure succesor(k, st, as)

;Rol: atribuie elementului st[k] din


stiv valoarea urmtoare din
mulimea Sk

Parametri: as - variabil boolean care


ntoarce valoarea adevrat dac
function solutie(k): boolean;
elementul situat pe nivelul k are
Rol: verific dac s-au determinat toate
succesor, st - stiv ,k - nivelul in stiv
elementele din stiv ce constituie vectorul soluie
al problemeiParametri: k - nivelul in stiv

procedure validare(k, st, ev);


Rol: verific dac elementul pus pe nivelul k n
stiv ndeplinete restriciile ntre elementele
distinctive
Parametri: k - nivelul in stiv , st - stiv , ev variabil boolean care ntoarce valoarea
adevrat dac elementul situat pe nivelul k este
valid sau nu
procedure tipar;
Rol: listeaz soluia determinat

PROBLEME CU
BACKTRACKING

01 PROBLEMA CALULUI

02 - PERMUTRI

03 - ARANJAMENTE

04 - LABIRINT

05 PROBLEMA REGINEI

06 - COMBINRI

07 PRODUS CARTEZIAN

08 - PARTIII

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