Documente Academic
Documente Profesional
Documente Cultură
n=20
n=40
n=60
1 sec
58 min
12,7 zile
3855 secole
0,2 sec
366 secole
1013 secole
Descrierea metodei
Fie X=X1 ... Xn. Caut xX cu (x), unde :X {0,1} este o
proprietate definit pe X.
Din cele de mai sus rezult c generarea tuturor elementelor produsului
cartezian X nu este acceptabil.
Metoda backtracking ncearc, dar nu reuete totdeauna, micorarea timpului
de calcul. X este numit spaiul soluiilor posibile, iar sintetizeaz condiiile interne.
Vectorul x este construit progresiv, ncepnd cu prima component. Se
avanseaz cu o valoare xk dac este satisfcut condiia de continuare
k(x1,...,xk). Condiiile de continuare rezult de obicei din ; ele sunt strict
necesare, ideal fiind s fie i suficiente.
Distingem urmtoarele cazuri posibile la alegerea lui xk:
1)
Atribuie i avanseaz: mai sunt valori neconsumate din Xk i valoarea xk
aleas satisface k se mrete k.
2)
ncercare euat: mai sunt valori neconsumate din Xk i valoarea xk
aleas dintre acestea nu satisface k se va relua, ncercndu-se alegerea
unei noi valori pentru xk.
3)
"Revenire": nu mai exist valori neconsumate din Xk (Xk epuizat)
ntreaga Xk devine disponibil i kk-1.
4)
"Revenire dup determinarea unei soluii": este reinut soluia.
Reinerea unei soluii const n apelarea unei proceduri retsol care
prelucreaz soluia (o tiprete, o compar cu alte soluii etc.) i fie oprete procesul
(dac se dorete o singur soluie), fie prevede kk-1 (dac dorim s determinm
toate soluiile.
Notm prin CkXk mulimea valorilor consumate din Xk. Algoritmul este
urmtorul:
Ci, i;
k1;
while k>0
if k=n+1
then retsol(x); kk-1;
{ revenire dup obinerea unei soluii }
else if CkXk
then alege vXk\Ck; CkCk{v};
if k(x1,,xk-1,v)
then xkv; kk+1;
{ atribuie i avanseaz }
else
{ ncercare euat }
else Ck; kk-1;
{ revenire }
{ atribuie i avanseaz }
{ ncercare euat }
{ revenire }
Exemple
n exemplele care urmeaz, k va fi notat n continuare prin cont(k). Se
aplic algoritmul de mai sus pentru diferite forme ale funciei de continuare.
1) Colorarea hrilor. Se consider o hart. Se cere colorarea ei folosind cel mult
n culori, astfel nct oricare dou ri vecine (cu frontier comun de lungime
strict pozitiv) s fie colorate diferit.
Fie xk culoarea curent cu care este colorat ara k.
function cont(k: integer): boolean;
b true; i 1;
while b and (i<k)
if vecin(i,k) & xi=xk
then b false
else i i+1
cont b
end;
x2
xk
Variante
Variantele cele mai uzuale ntlnite n aplicarea metodei backtracking sunt
urmtoarele:
- soluia poate avea un numr variabil de componente
i/sau
- dintre ele alegem una care optimizeaz o funcie dat.
Exemplu. a=(a1,...,an)Zn. Caut un subir cresctor de lungime maxim.
Deci caut 1x1<...<xkn cu
k maxim
ax1 < ax2 <...< axk
procedure retsol(k)
if k>kf then xfx; kfk;
end;
Varianta recursiv
O descriem pentru nceput pentru X1=...=Xn={1,...,s}.
Apelul iniial este: back(1).
procedure back(k)
if k=n+1
then retsol
else for i=1,s
xki;
if cont(k)
then back(k+1); revenire din recursivitate
else
end.
Variante:
cum pot ajunge ntr-o poziie (i1,j1) dat?
se cere determinarea componentelor conexe.
Micrile posibile sunt date printr-o matrice depl cu dou linii i ndepl
coloane. De exemplu, dac deplasrile permise sunt cele ctre poziiile
vecine situate la Est, Nord, Vest i Sud, matricea are forma:
1
0
1
1 0
0 1
class elem {
int i,j; elem prec;
static int m,n,i0,j0,ndepl;
static int[][] mat;
static int[][] depl = { {1,0,-1,0}, {0,-1,0,1} };
static { ndepl = depl[0].length; }
elem() {
int i,j;
IO.write("m,n = "); m = (int) IO.read();
n = (int) IO.read();
// de fapt m+2,n+2
mat = new int[m][n];
= (int) IO.read();
2; mat[m-1][i] = 2; }
2; mat[j][n-1] = 2; }
IO.read();
}
elem(int ii, int jj, elem x) { i = ii; j = jj; prec = x; }
String print(elem x) {
if (x == null) return "(" + i + "," + j + ")";
else return x.print(x.prec)+" "+"("+i+","+j+")";
}
void p() {
elem x; int ii,jj;
for (int k=0; k<ndepl; k++) {
ii = i+depl[0][k]; jj = j+depl[1][k];
if (mat[ii][jj] == 1);
else if (mat[ii][jj] == 2) IO.writeln(print(prec));
else if (mat[ii][jj] == 0) {
mat[i][j] = -1; x = new elem(ii,jj,this);
x.p(); mat[i][j] = 0;
}
}
}
class DrumPlan {
public static void main(String[] args) {
new elem(); elem start = new elem(elem.i0,elem.j0,null);
start.p();
}
}
m,n =
1 1 0
0 1 0
1 0 0
i0,j0
5 6
1
1
1
= 2 2
0
0
(i0,j0)
3
0
2
1