Sunteți pe pagina 1din 6

4.

Metoda mixt
Sritura calului
Avem o tabel de ah, de dimensiune standard 8 x 8, pe care se afl diverse piese de ah. Un cal
se afl pe poziia (i,j). Dorim s mutm calul pe poziia (k,l) - dac acest lucru este posibil
folosind oricare din cele 8 mutri posibile ale calului n orice succesiune, astfel nct numrul de
mutri s fie minim.
Intrarea este dat dintr-o matrice de caractere de forma
********
*-******
********
***-****
********
****-***
unde "-" nseamn poziia curent, iar "*" poziia liber.
Poziia n care se poate afla calul trebuie s fie liber.
O metod de rezolvare ar fi backtracking. Inconvenientul este c am calcula atunci un
drum de mai multe ori, ceea ce contravine logicii pure.
Algoritmul folosit la rezolvarea acestei probleme se numete algoritmul lui Lee i este o
variant mai "ciudat" a programrii dinamice.
n acest algoritm se face de fapt o parcurgere a unui graf, cu dorina de a ne ndeprta ct
mai puin de punctul de plecare, i n mod treptat. De obicei n algoritmul lui Lee un nod
reprezint o stare a unui sistem, iar un arc - o transformare. Este o metod de rezolvare a
problemelor n care se cere numrul minim de operaii necesare pentru a ajunge la un obiectiv.
n situaia de fa: matricea are semnificaia c sunt necesare mutri ale calului pentru a
ajunge n poziia (i,j). Elementul corespunztor poziiei iniiale are valoarea zero, iar pe noi ne
intereseaz elementul care indic poziia final. Prin algoritmul lui Lee se calculeaz de fapt
matricea drumurilor minime. Dezavantajul este acela c dac dorim s refacem drumul soluiei,
este necesar o structur auxiliar de date.
Programul funcioneaz n felul urmtor:
1. Se consider c nu este nevoie de nici o mutare pentru a ajunge la starea iniial, deci
elementul corespunztor se consider atins cu pasul 0;
2. Pentru toate elementele atinse la pasul anterior (aici 0) se calculeaz poziiile n care se
poate ajunge din ele; pentru fiecare astfel de poziie, dac nu a mai fost atins, se atinge acum la
pasul curent (adic 1);

1
2. Problema se reia pentru pasul 1 ca pas anterior i pasul 2 - pas curent etc;
3. Dac la un pas i nu se mai poate ajunge la un nod nou, algoritmul se termin (n cazul
problemei noastre, ieirea din ciclul de marcare a nodurilor n pai succesivi se face
dac n pasul curent nu s-a mai atins nici un nod nou).
4. Ordin de complexitate al algoritmului este N2
Programul Pascal este urmtorul:
Program cal;
uses crt;
label 1;
var t:array [1..8,1..8] of char;
a:array [1..8,1..8] of integer;
pas,i,j,k,l,ic,jc,kc,lc:integer;
modificare:boolean; fi:text;

Function poate_sari(i, j:integer;


var k,l:integer;ai,aj:integer):boolean;
begin
k:=i-ai; l:=j-aj;
if (k in [1..8]) and (l in [1..8]) and (t[k,l]='-') and (a[k,l]>pas)
then poate_sari:=true
else poate_sari:=false
end;

Procedure marcheaza(i,j:integer);
begin
a[i,j]:=pas+1;
modificare:=true;
end;

Begin
clrscr;
writeln('va rugam sa dati pe liniile configuratia tabelei:');
for i:=1 to 8 do
begin
for j:=1 to 8 do read(t[i,j]);readln;
end;
writeln;
write('pozitia initiala a calului, adica i si j:');
readln(ic,jc);
write('pozitia finala a calului, adica k si l:');
readln(kc,lc);
if (t[ic,jc]='*') or (t[kc,lc]='*') then
begin
writeln('deplasarea inposibila !'); goto 1;
end;
for i:=1 to 8 do
for j:=1 to 8 do a[i,j]:=65;
a[ic,jc]:=0; pas:=0; modificare:=true;

while modificare do
begin
modificare:=false;
for i:=1 to 8 do
for j:=1 to 8 do
if (a[i,j]=pas) then begin
if poate_sari(i,j,k,l,1,2) then marcheaza(k,l);
if poate_sari(i,j,k,l,-1,2) then marcheaza (k,l);
if poate_sari(i,j,k,l,1,-2) then marcheaza (k,l);
if poate_sari(i,j,k,l,-1,-2) then marcheaza (k,l);

2
if poate_sari(i,j,k,l,2,1) then marcheaza (k,l);
if poate_sari(i,j,k,l,2,-1) then marcheaza (k,l);
if poate_sari(i,j,k,l,-2,1) then marcheaza (k,l);
if poate_sari(i,j,k,l,-2,-1) then marcheaza (k,l);
end;
if a[kc,lc]<>65 then
begin
i:=8;j:=8;
modificare:=false;
end;
{daca am ajuns in situatia finala nu mai are
rost sa calculam matricea}
pas:=pas+1;
end;
if a[kc,lc]=65 then writeln ('Deplasarea inposibila !')
else
begin
writeln('Deplasarea din(',ic,',',jc,') in (',kc,',',lc,')');
writeln('Se poate face prin ',a[kc,lc],' mutari.');
end;
1:readkey;
End.

Rezultatul realizrii programului:

Acesta este genul de problem la care se poate aplica matricea drumurilor minime, prin
programarea dinamic. Avem aici o tehnic de programare auxiliar n sensul c permite
aducerea unei probleme la una cunoscut, pe care o numim liniarizare de matrice.
Iniial am avut o problem n care era dat o matrice de dimensiuni 8 x 8 care simboliza
ocuparea sau neocuparea unor poziii pe tabla de ah. Tehnica liniarizare consta n a considera

3
fiecare element al matricii ca fiind un nod al unui graf.
De exemplu elementului A[i,j] al matricei va deveni nodul (i -1) * 8+j unde 8 este numrul
de coloane al matricei. Matricea este de forma:
A[ 1,1] A[ 1,2] . . . . A[ 1,8]
A[ 2,1] A[ 2,2] . . . . A[ 2,8]
...
A[ 8,1] A[ 8,2] . . . . A[ 8,8]
Este ca i cum am considera fiecare element al matricii ca fiind o entitate, (nod) dar pe rnd:
prima linie primul element, prima linie al doilea element, .., a doua linie primul element, .. , i le-
am numerotat in ordine cresctoare ncepnd cu 1. Corespondena ntre elementul de coordonare
(i,j) i nodul (i-1) * 8+j unde i este numrul liniei, iar j numrul coloanei, se poate verifica foarte
uor c este biunivoc.
Odat considerat un graf simplu, putem construi matricea drumurilor minime, lucru care n
exemplu nostru este notat prin A[i,j] cu 1i64 , 1j64. n acest graf vom construi o muchie
ntre nodul (i -1) * 8+j i (k-1)*8+l dac poziiile (i,j) respectiv (k,l) de pe tabla noastr sunt
libere i pot ajunge prin sritur direct de la (i,j) la (k,l). Ponderea arcului pe care l facem va fi 1,
exact numrul de srituri pe care le facem pentru deplasare ntre dou poziii.
Dup ce calculm matricea drumurilor minime, A[(i-1)*8+j i (k-1)*8+l] va arta exact
numrul minim de srituri ale calului pentru a ajunge din poziia (i,j) n poziia (k,l).

Atragem atenia c multe probleme se vor rezolva prin liniarizri de matrici, lucrul care
impune o atenie mrit acestei metode. Ca un dezavantaj, n unele probleme se poate dori
liniarizarea unei matrice foarte mari, deci metoda necesit mult spaiu. Deoarece ns tendinele
actuale se ndreapt spre micorarea timpului de rulare al unui program, sfatul nostru este acela
c ntotdeauna ntre un algoritm care necesit mult spaiu i unul care necesit mult timp de
rulare, s l preferai pe cel care va funciona mai rapid.
Observaie: Algoritmul lui Lee este mai performant dect cel de liniarizare, avnd ordinul de
complexitate N2.

Problema perechilor de numere


Se d o pereche de numere de forma (a,b) asupra creia putem face urmtoarele operaii:
1. (a,b) (a - b, b)
2. (a,b) (a +b, b)
3. (a,b) (b,a).
Dndu-se valorile (a,b) s se spun care este numrul minim de operaii pe care trebuie s le

4
facem astfel nct s ajungem la perechea (c,d) dac acest lucru este posibil, sau Nu se poate
dac nu este posibil.
Programul Pascal este:
Program pereche;
uses crt;
const nmax=100;
infinit=nmax*nmax+1;
var t:array [1..nmax,1..nmax] of integer;
pas,i,j,a,b,c,d:integer; modificare:boolean;
Function neatins(i,j:integer):boolean;
begin
if (i in [1..nmax]) and (j in [1..nmax]) and (t[i,j]=infinit)
then neatins:=true
else neatins:=false
end;
Procedure atinge(i,j:integer);
begin
t[i,j]:=pas+1; modificare:=true
end;
Begin
clrscr;
write('Dati perechea a b '); readln(a,b);
write('Dati perechea c d '); readln(c,d);
for i:=1 to nmax do
for j:=1 to nmax do t[i,j]:=infinit;
t[a,b]:=0; pas:=0; modificare:=true;
while modificare do
begin
modificare:=false;
for i:=1 to nmax do
for j:=1 to nmax do
if t[i,j]=pas then
begin
if neatins(i+j,j) then atinge(i+j,j);
if neatins(i-j,j) then atinge(i-j,j);
if neatins(j,i) then atinge(j,i);
if t[c,d]<>infinit then
begin
i:=nmax; j:=nmax;
modificare:=false;
end;
end;
pas:=pas+1;
end;
if t[c,d] =infinit then
writeln('Nu se poate ajunge la perechea data ! ')
else begin
writeln('Este nevoie de ',t[c,d],' operatii pentru a ajunge de la');
writeln('perechea (',a,',',b,') la perechia(',c,',',d,') ! ')
end;
readkey;
End.

5
Rezultatul rulrii programului este:

Se folosete strategia Lee, n care matricea T[i,j] are semnificaia c plecnd de la


perechea iniial se poate ajunge la perechea (i,j) n T[i,j] moduri.

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