Documente Academic
Documente Profesional
Documente Cultură
Rezolvarea problemelor
folosind metoda
backtracking
Slide-uri realizate de
prof. Florentin Ipate
Exemplu: ieirea din labirint
2
Exemplu: aranjarea a n regine
3
Exemplu: rezolvarea unui sudoku
4
Exemplu: rezolvarea unui sudoku
5
Agenda
Metoda Backtracking: prezentare general
Varianta nerecursiv
Varianta recursiv
Exemple
Generarea permutrilor, aranjamentelor, combinrilor
Problema celor n regine
Problema colorrii hrilor
iruri de paranteze ce se nchid corect
Partiiile unui numr natural
Probleme de backtracking date la admitere
6
Metoda Backtracking
Se folosete n cazul problemelor a cror soluie este un
vector x = (x1, x2, ..., xn) unde fiecare xi apartine unei
mulimi finite Ai, elementele mulimilor Ai aflndu-se ntr-
o relaie de ordine bine stabilit.
ntre componentele xi ale vectorului sunt precizate anumite
relaii numite condiii interne.
8
Metoda Backtracking
Backtracking = parcurgerea limitat (conform
condiiilor de continuare) n adncime a unui
arbore.
Spaiul soluiilor este organizat ca un arbore
un vrf este viabil dac sunt anse s se
gseasc o soluie explornd subarborele cu
rdcina n acel vrf
sunt explorai numai subarborii cu rdcini
viabile
9
Backtracking nerecursiv
k1;
ct timp k > 0 repet
dac ( k = n+1 ) atunci {am gsit o soluie}
prelucreaz(x1,..., xn); {afieaz soluie}
kk-1; {revenire dup gsirea soluiei}
altfel
dac ( netestat) atunci
xkv; { atribuie }
dac (x1,...,xk ndeplinete cond. continuare)
atunci
kk+1; { avanseaz }
sfrit dac
altfel
kk-1; { revenire }
sfrit dac
sfrit ct timp
10
Pentru cazul particular Ai ={1, 2,,n}, i=1,...,n, algoritmul se
rescrie astfel:
xi 0, i=1,...,n
k1;
ct timp k > 0 repet
dac ( k = n+1 ) atunci {am gsit o soluie}
prelucreaz(x1,..., xn); {afieaz soluie}
kk-1; {revenire dup gsirea soluiei}
altfel
dac (xk<n) atunci
xk xk + 1; { atribuie }
dac (x1,...,xk ndeplinete cond. continuare)
atunci
kk+1; { avanseaz }
sfrit dac
altfel
xk0; kk-1; { revenire }
sfrit dac
sfrit ct timp
11
Backtracking recursiv
Descriem varianta recursiv pentru cazul particular
Ai ={1, 2,,n}, i=1,...,n. Apelul iniial este backrec(1).
procedura backrec(k)
dac (k=n+1) atunci {am gsit o soluie}
prelucreaz(x1,..., xn); {afieaz soluie}
altfel
i1;
ct timp i<=n repet {toate valorile posibile }
xki;
dac (x1,...,xk ndeplinete cond. continuare)
atunci backrec(k+1);
sfrit dac
ii+1;
sfrit ct timp
sfrit dac
sfrit procedura 12
Exemple
1. Generarea permutrilor, aranjamentelor,
combinrilor
2. Problema celor n regine
3. Colorarea hrilor
4. iruri de paranteze ce se nchid corect
5. Partiiile unui numr natural
13
Generarea permutrilor
Se citete un numr natural n. S se genereze
toate permutrile mulimii {1, 2, , n}.
Reprezentarea soluiei ?
Condiii interne ?
Condiii de continuare ?
14
Exemplu: n = 3
= {1,2,3} {1,2,3} {1,2,3}
x = (x1, x2, x3)
1 2 3
1 2 3 1 2 3 1 2 3
1
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
15
1 2 3 1
1 2 2 2 2 3 3
1 1 1 1 1 1 1 1
2 3 1 2 3
3 3 1 1 1 1 2
1 1 2 2 2 2 2 2
1 2 3 1 2
3 3 3 3 1 1 1
2 2 2 2 3 3 3 3
3 1 2 3
1 2 2 2 2 3
3 3 3 3 3 3
16
type stiva = array[1..20] of int n, nrsol = 0, x[20];
integer;
var n,nrsol:integer;
procedure tipar(x:stiva); void tipar(int x[])
var i:integer; {
begin nrsol++;
nrsol := nrsol+1; printf("Solutia %d:",
write('Solutia ',nrsol,': '); nrsol);
for i:=1 to n do for(int i=0; i<n; i++)
write(x[i],' '); printf(" %d ", x[i]);
writeln; printf("\n");
end; }
function cont(x:stiva; int cont(int x[], int k)
k:integer):boolean; {
var i:integer; for(int i=0;i<k;i++)
begin if (x[i]==x[k])
cont:=true; return 0;
for i:=1 to k-1 do return 1;
if (x[i]=x[k]) then }
cont:=false;
end;
17
procedure back(); void back()
var k,i:integer; {
begin int k = 0;
for i:=1 to n do x[i]:=0; for(int i=0; i<n; i++)
k:=1; x[i]=0;
while k>0 do while(k > -1)
begin {
if k=n+1 then begin if (k==n) {
tipar(x); tipar(x);
k:=k-1; k--; }
end else
else if(x[k]<n)
if x[k]<n then {
begin x[k]++;
x[k]:=x[k]+1; if (cont(x,k))
if cont(x,k) then k++;
k:=k+1; }
end else {
else begin x[k]=0;
x[k]:=0; k--;
k:=k-1; }
end; }
end; }
end; 18
procedure backrec(k:integer); void backrec(int k)
var i:integer; {
begin if(k==n)
if k=n+1 then tipar(x);
tipar(x) else
else for(int i=1;i<=n ;i++)
for i:=1 to n do {
begin x[k]=i;
x[k]:=i; if (cont(x,k))
if cont(x,k) then backrec(k+1);
backrec(k+1); }
end }
end;
BEGIN int main()
write('Dati n: '); readln(n); {
nrsol := 0; printf("Dati n:");
back(); scanf("%d",&n);
{ sau } back();
{ backrec(1); } // sau
readkey; // backrec(0);
END. return 0;
}
19
Problema celor n regine
Fiind dat o tabl de ah de dimensiune n x n, se
cer toate soluiile de aranjare a n regine astfel
nct s nu atace (s nu se afle dou regine pe
aceeai linie, coloan sau diagonal).
1 2 3 4 1 2 3 4
1 Reprezentarea soluiei ? 1
2 Condiii interne ? 2
3 Condiii de continuare ? 3
4 4
21
Generarea aranjamentelor
Se citesc dou numere naturale n i p. S se
genereze toate submulimile mulimii {1,2, ..., n}
de p elemente. Dou mulimi cu aceleai elemente,
la care ordinea acestora difer, sunt considerate
diferite.
n=3, p=2
Reprezentarea soluiei ? 12
Condiii interne ? 13
Condiii de continuare ? 21
23
31
x = (x1, x2,, xp)
32
Condiii interne: pentru orice ij, xixj
Condiii de continuare: pentru orice i<k, xixk
22
Algoritmul este acelai ca la permutri, se modific doar
dimensiunea stivei
24
Algoritmul este acelai ca la aranjamente, se modific n plus
funcia de continuare
26
Colorarea hrilor
Se consider o hart. Se cere colorarea ei folosind cel
mult 4 culori, astfel nct oricare dou ri vecine s fie
colorate diferit.
Reprezentarea soluiei ?
Condiii interne ?
Condiii de continuare ?
30
Exist soluii n este par.
Reprezentarea soluiei: x = (x1, x2,, xn), unde xk
{'(', ')'}
Notm dif = nr( - nr) la pasul k
Condiii interne (finale)
dif = 0
dif 0 pentru orice secven {x1, x2,, xk}
Condiii de continuare
dif 0 doar necesar
dif n k i suficient
Observaie. n implementarea urmtoare backtracking-ul
este optimal: se avanseaz dac i numai dac suntem
siguri c vom obine cel puin o soluie. Cu alte cuvinte,
condiiile de continuare nu sunt numai necesare, dar i
suficiente.
31
procedure backrec(k:integer); void backrec(int k)
begin {
if(k=n+1) then if(k==n)
tipar(x) tipar(x);
else else
begin {
x[k]:='('; x[k]='(';
dif:=dif+1; dif++;
if(dif <= n-k+1) then if (dif <= n-k)
backrec(k+1); backrec(k+1);
dif:=dif-1; dif--;
x[k]:=')'; x[k]=')';
dif:=dif-1; dif--;
if(dif >= 0) then if (dif >= 0)
backrec(k+1); backrec(k+1);
dif:=dif+1; dif++;
end; }
end; }
if(n mod 2=0) then if (n%2==0)
begin {
dif:=0; dif=0;
backrec(1); backrec(0);
end; }
32
Partiiile unui numr natural
Dat un numr natural n, s se genereze toate partiiile lui
n ca sum de numere pozitive (x1, x2,, xk {1,2,,n}
cu proprietatea x1+ x2 ++ xk = n).
33
Reprezentarea soluiei: x = (x1, x2,, xk) (stiv de
lungime variabil!), unde xi {1,2,,n}
Condiii interne (finale)
x1+ x2 ++ xk = n
pentru unicitate: x1 x2 xk
Condiii de continuare
xk-1 xk (avem xk {xk-1,,n})
x1 + x2 +... + xk n
34
begin void back(){
k:=1; s:=0; int k=0, s=0;
while(k>=1) do while(k>=0){
begin
if(x[k]<n){
if(x[k]<n) then
begin x[k]++; s++;
x[k]:=x[k]+1; s:=s+1; if(s<=n) { //cond.cont.
if (s<=n) if(s==n){ // solutie
then begin tipar(x,k);
if(s=n) then begin s=s-x[k]; k--;
tipar(x,k); //revenire
s:=s-x[k]; }
k:=k-1;
else
end
else begin { //avansare
k:=k+1; k++;
x[k]:=x[k-1]-1; x[k]=x[k-1]-1;
s:=s+x[k]; s+=x[k];
end; }
end }
else begin else {//revenire
s:=s-x[k];
s=s-x[k]; k--;
k:=k-1;
end; }
end; }
end; }
end; } 35
Probleme date la admitere care
se pot rezolva cu metoda
backtracking
1. Generarea unor numere cu proprieti
specificate
2. Generarea produsului cartezian
3. Generarea tuturor soluiilor unei probleme,
pentru a alege dintre acestea o soluie care
minimizeaz sau maximizeaz o expresie
36
Problem (admitere 2012)
Utiliznd metoda backtracking se genereaz toate
numerele cu cte trei cifre impare, cifre care
aparin mulimii {7,8,1,6,2,3}. Primele 4 soluii
generate sunt, n aceast ordine: 777, 771, 773,
717. Cea de a 8-a soluie generat este:
a) 737 b) 788 c) 717 d) 731
{7,8,1,6,2,3} {7,8,1,6,2,3}
Solutia 1: 777 Solutia 5: 711
Solutia 2: 771 Solutia 6: 713
Solutia 3: 773 Solutia 7: 737
Solutia 4: 717 Solutia 8: 731
37
Algoritmul este asemnator cu cel de la aranjamente
var cif: array[1..6] of int n=6, p=3, nrsol = 0,
integer = (7,8,1,6,2,3); x[3];
int cif[]={7,8,1,6,2,3};
procedure tipar(x:stiva); void tipar(int x[])
var i:integer; {
begin nrsol++;
nrsol := nrsol+1; printf("Sol. %d:", nrsol);
write('Sol. ',nrsol,': '); for(int i=0; i<p; i++)
for i:=1 to p do printf("%d", cif[x[i]-1]);
write(cif[x[i]],' '); printf("\n");
writeln; }
end;
function cont(x:stiva; int cont(int x[], int k)
k:integer):boolean; {
begin if (cif[x[k]-1]%2==0)
cont:=true; return 0;
if cif[x[k]] mod 2 = 0 then return 1;
cont:=false; }
end;
38
Problem (admitere 2006)
39
a:array[1..4] of integer=(1,8,1,1); int n=4, nrsol = 0, x[4];
b:array[1..4] of integer=(2,9,2,9); int a[]={1,8,1,1},
b[]={2,9,2,9};
procedure back(); void back()
var k,i:integer; {
begin int k = 0;
for i:=1 to n do for(int i=0; i<n; i++)
x[i]:=a[i]-1; x[i]=a[i]-1;
k:=1; while(k > -1){
while k>0 do begin if (k==n) {
if k=n+1 then tipar(x);
begin k--;
tipar(x); k:=k-1; }
end else
else if (x[k]<b[k]){
if x[k]<b[k] then x[k]++; k++;
begin }
x[k]:=x[k]+1; k:=k+1; else
end {
else begin x[k]=a[k]-1;
x[k]:=a[k]-1; k:=k-1; k--;
end; }
end; }
end; } 40
procedure void backrec(int k){
backrec(k:integer);
var i:integer;
begin
if k=n+1 then if(k==n)
tipar(x) tipar(x);
else else
for i:=a[k] to b[k] do for(int i=a[k];i<=b[k];i++){
begin x[k]=i;
x[k]:=i; backrec(k+1);
backrec(k+1); }
end }
end;
41
Problem (admitere 2011, enun
modificat)
Se d un vector v de n elemente egale cu 1. Prin partiie a
vectorului v nelegem o mprire a vectorului n
subvectori, astfel nct fiecare element al vectorului v
apare exact o dat ntr-unul dintre subvectori. Pentru
fiecare partitie a vectorului v n p subvectori
, , !" , # , , #!$ , , % , , %!& , se calculeaz
produsul sumelor elementelor din fiecare subvector al
%
partiiei, adic * ( .
a) S se citeasc n, p de la tastatur i s se scrie un
program care determin cel mai mare produs
calculat n acest fel pentru toate partiiile n p
subvectori ale vectorului v.
b) Exist o soluie la punctul a) care s nu calculeze
toate produsele posibile? Justificai.
42
ntrebare
Se dau n = 11, p=3. Care este cel mai mare produs
%* ( pentru toate partiiile n p subvectori ale
vectorului v?
a) 21
b) 30
c) 48
d) 64
Observaie: n1 + n2 + + np = n.
43
Exemplu
n = 11, p = 3: n1 + n2 + n3 = 11
[ [1,1,1] , [1,1,1,1] , [1,1,1,1] ]
n1 =3, n2 = 4, n3 = 4, n1n2n3 = 48
n1 n2 n3 Produs
1 1 9 9
1 2 8 16
1 3 7 21
3 3 5 45
3 4 4 48
44
var n,p,nrsol,prod_max:integer; int n, p, nrsol = 0,
nrsol := 0; prod_max := 0; x[20], prod_max=0;
45
function cont(x:stiva; int cont(int x[], int k)
k:integer):boolean; {
var s,i:integer; int s = 0;
begin
s := 0; cont:=true; if (k>0)
if k>1 then if (x[k] < x[k-1])
if x[k]<x[k-1] then return 0;
cont:=false;
for i:=1 to k do s:=s+x[i]; for (int i=0; i<=k; i++)
if s>n then s = s + x[i];
cont:=false; return (s<=n);
end; }
function solutie(x:stiva; int solutie(int x[], int k)
k:integer):boolean; {
var s,i:integer;
begin
s := 0; solutie:=true; int s = 0;
if k<>p+1 then if (k!=p)
solutie := false; return false;
for i:=1 to p do for (int i=0; i<p; i++)
s := s + x[i]; s = s + x[i];
if s <> n then return (s==n);
solutie:=false; }
end; 46
procedure back(); void back(){
var k,i:integer;
begin int k = 0;
for i:=1 to p do x[i]:=0; for(int i=0; i<p; i++)
k:=1; x[i]=0;
while k>0 do while(k > -1)
begin {
if solutie(x,k) then if (solutie(x,k))
begin {
tipar(x); tipar(x);
k:=k-1; k--;
end }
else else
if x[k]<n then if(x[k]<n)
begin {
x[k]:=x[k]+1; x[k]++;
if cont(x,k) then if (cont(x,k))
k:=k+1; k++;
end }
else begin else {
x[k]:=0; x[k]=0;
k:=k-1; k--;
end; }
end; }
47
end; }
Exist o soluie la punctul a) care s nu
calculeze toate produsele posibile? Justificai!
+,-./
0 %12 30 4 152
48
ntrebare
Se dau n = 26, p=4. Care este cel mai mare produs
%* ( pentru toate partiiile n p subvectori ale
vectorului v?
a) 1375
b) 1820
c) 1764
d) 1728
49
Exerciii propuse
1. Generarea tuturor submulimilor mulimii {1,2, ..., n}.
2. Generarea submulimilor unei mulimi cu elemente
arbitrare {a1,a2, ..., an}.
3. Generarea partiiilor unei mulimi.
4. Se d o sum s i n tipuri de monede avnd valorile a1,
a2, , an lei. Se cer toate modalitile de plat a sumei
s utiliznd tipurile de monede date.
5. S se determine numerele A de n cifre,
# !
cu 1,2 , 7
1. . (, care sa fie divizibile cu 2n.
50
V mulumesc!
Succes la examenul de
admitere!
51