Sunteți pe pagina 1din 19

Ministerul Educaiei a Republicei Moldovei

Universitatea Tehnic a Moldovei

Lucrare de
laborator Nr. 4
La obiectul: Analiza i Proiectarea Algoritmilor.

Tema: Metoda programrii dinamice.

A elaborat: studentul gr. TI-142


Caldare V.

A verificat: prof. univ.


Bagrin V.
Chiinu 2015

Tema: Metoda programrii dinamice

Scopul lucrrii:
1. Studierea metodei programrii dinamice.
2. Analiza i implementarea algoritmilor de
programare dinamic.
3. Compararea tehnicii greedy cu metoda de
programare dinamic.
2.1 Cele mai scurte drumuri care pleac din acelai punct

Fie G = <V, A> un graf orientat, unde V este mulimea vrfurilor i A este
mulimea arcelo. Fiecare arc are o lungime nenegativa. Unul din vrfuri este ales c
vrf surs. Problema este de a determina lungimea celui mai scurt drum de la surs
ctre fiecare vrf din graf.
Se va folosi un algoritm greedy, datorat lui Dijkstra (1959). Notm cu C
mulimea vrfurilor disponibile (candidaii) i cu S mulimea vrfurilor deja selectate.
n fiecare moment, S conine acele vrfuri a cror distan minim de la surs este
deja cunoscut, n timp ce mulimea C conine toate celelalte vrfuri. La nceput, S
conine doar vrful surs, iar n final S conine toate vrfurile grafului. La fiecare pas,
adugam n S acel vrf din C a crui distan de la surs este cea mai mic.
Se spune, c un drum de la surs ctre un alt vrf este special, dac toate
vrfurile intermediare de-a lungul drumului aparin lui S. Algoritmul lui Dijkstra
lucreaz n felul urmtor. La fiecare pas al algoritmului, un tablou D conine
lungimea celui mai scurt drum special ctre fiecare vrf al grafului. Dup ce se
adaug un nou vrf v la S, cel mai scurt drum special ctre v va fi, de asemenea, cel
mai scurt dintre toate drumurile ctre v. Cnd algoritmul se termin, toate vrfurile
din graf sunt n S, deci toate drumurile de la surs ctre celelalte vrfuri sunt
speciale i valorile din D reprezint soluia problemei.
Presupunem c vrfurile sunt numerotate, V = {1, 2, ..., n}, vrful 1 fiind sursa,
i c matricea L d lungimea fiecrui arc, cu L[i, j] = , dac arcul (i, j) nu exist.
Soluia se va construi n tabloul D[2 .. n]. Algoritmul este:

function Dijkstra(L[1 .. n, 1 .. n])


1: C {2, 3, ..., n} {S = V \C exist doar implicit}
2: for i 2 to n do D[i] L[1, i]

3: repeat n2 times
4: v vrful din C care minimizeaz D[v]
5: C C \ {v} {si, implicit, S S {v}}
6: for fiecare w C do
7: D[w] min(D[w], D[v]
+L[v, w]) return D

Proprietatea 1. n algoritmul lui Dijkstra, dac un vrf i


a) este n S, atunci D[i] d lungimea celui mai scurt drum de la surs ctre i;
b) nu este n S, atunci D[i] d lungimea celui mai scurt drum special de la surs ctre i.
La terminarea algoritmului, toate vrfurile grafului, cu excepia unuia, sunt n S. Din
proprietatea
precedenta, rezulta c algoritmul lui Dijkstra funcioneaz corect.

2.2 Determinarea celor mai scurte drumuri intr-un graf


Fie G = <V, A> un graf orientat, unde V este mulimea vrfurilor i A este mulimea
arcelor. Fiecrui
arc i se asociaz o lungime nenegativ. S se calculeze lungimea celui mai scurt
drum ntre fiecare pereche de varfuri.
Vom presupune c vrfurile sunt numerotate de la 1 la n i c matricea L d
lungimea fiecrui arc: L[i, i] = 0, L[i, j] 0 pentru i j, L[i, j] = dac arcul
(i, j) nu exist.
Principiul optimalitii este valabil: dac cel mai scurt drum de la i la j trece
prin varful k, atunci poriunea de drum de la i la k, ct i cea de la k la j, trebuie s
fie, de asemenea, optime.
Construim o matrice D care s conin lungimea celui mai scurt drum ntre
fiecare pereche de vrfuri. Algoritmul de programare dinamic iniializeaz pe D cu
L. Apoi, efectueaz n iteraii. Dup iteraia k, D va conine lungimile celor mai scurte
drumuri care folosesc ca vrfuri intermediare doar vrfurile din
{1, 2, ..., k}. Dup n iteraii, obinem rezultatul final. La iteraia k, algoritmul trebuie
s verifice, pentru fiecare pereche de vrfuri (i, j), dac exist sau nu un drum,
trecnd prin varful k, care este mai bun dect actualul drum optim ce trece doar
prin vrfurile din {1, 2, ..., k Dk matricea D dup iteraia k. Verificarea
necesar este atunci:

Dk[i, j] = min(Dk-1[i, j], Dk-1[i, k] Dk-1[k, j])

unde s-a facut uz de principiul optimalitii pentru a calcula lungimea celui mai scurt
drum fa de k. Implicit, s-a considerat c un drum optim care trece prin k nu poate
trece de dou ori prin k.

Acest algoritm simplu este datorat lui Floyd (1962):

function Floyd(L[1 .. n, 1 .. n])


1: array D[1 .. n, 1 .. n]
2: D L
3: for k 1 to n do
4: for i 1 to n do
5: for j 1 to n do
6: D[i, j] min(D[i, j], D[i,
kD[k, j]) return D
Se poate deduce c algoritmul lui Floyd necesit un timp n O(n3). Un alt mod de a
rezolva aceast problem este s se aplice algoritmul Dijkstra prezentat mai sus de n
ori, alegnd mereu un alt vrf surs. Se obtine un timp n n O (n2), adic tot n O (n3).
Algoritmul lui Floyd, datorit simplitii lui, are ns constanta multiplicativ mai
mic, fiind probabil mai rapid n practic
Dijkstra :
#include <iostream>
#include <conio.h>
#include <fstream>
#include <iostream>
#include<time.h>
using namespace std;
const int V=6;
int it = 0;
//alg Dijkstra
void Dijkstra(int GR[V][V], int st)
{
int distance[V], count, index, i, u, m=st+1,INT_MAX=9999999;
bool visited[V];
for (i=0; i<V; i++)
{
distance[i]=INT_MAX;
visited[i]=false;
}
distance[st]=0;
for (count=0; count<V-1; count++)
{
int min=INT_MAX;
for (i=0; i<V; i++)
if (!visited[i] && distance[i]<=min)
{
min=distance[i]; index=i;
}
u=index;
visited[u]=true;
for (i=0; i<V; i++){
it++;
if (!visited[i] && GR[u][i] && distance[u]!=INT_MAX &&distance[u]
+GR[u][i]<distance[i])
distance[i]=distance[u]+GR[u][i];
}
}
cout<<"Costul din virgul initial pina in restul virfurilor: \t\n";
cout<<"-----------"<<endl;

for (i=0; i<V; i++)


if (distance[i]!=INT_MAX)

cout<<m<<" -> "<<i+1<<" = "<<distance[i]<<endl;


else cout<<m<<" -> "<<i+1<<" = "<<"inaccesibil"<<endl;
cout<<"-----------"<<endl;
}

int main()
{
setlocale(LC_ALL, "Rus");
clock_t start,end;
start=clock();

int GR[V][V];
/*int GR[V][V]={
{0, 1, 4, 0, 2, 0},
{0, 0, 0, 9, 0, 0},
{4, 0, 0, 7, 0, 0},
{0, 9, 7, 0, 0, 2},
{0, 0, 0, 0, 0, 8},
{0, 0, 0, 0, 0, 0}};
*/
ifstream f;
f.open("g6des.txt");
int x;

for (int i = 0; i <= V-1; i++)


{
for (int j = 0; j <= V-1; j++)
{
f >> x;
GR[i][j] = x;
}
}
f.close();

/*for (int i = 0; i <= V-1; i++)


{
for (int j = 0; j <= V-1; j++)
{
cout <<"\t"<<GR[i][j];
}cout << endl;
}
getch();*/

for(int i = 1; i < V+1;i++){


//cout<<"Virful initial >> "; //cin>>start;
start = i;
Dijkstra(GR, start-1);
end=clock();
}
printf("\n\nTimpul de executie este : %.8f \n",((double)(clock()-
start))/CLOCKS_PER_SEC);
cout <<endl<<"Nr iteratii: "<<it<<endl;

}
6 virfuri rar:
6 virfuri des:
15 virfuri rar:

15 virfuri des:
25 virfuri rar :

25 virfuri des:
250 virfuri:
Floyd:
#include <iostream>
#include <conio.h>
#include <fstream>
#include <iostream>
#include<time.h>
using namespace std;
const int maxV=1000;
int i, j, n;
int it = 0;
int GR[maxV][maxV];
//alg Floyd
void FU(int D[][maxV], int V)
{
int k;
for (i=0; i<V; i++) D[i][i]=0;

for (k=0; k<V; k++)


for (i=0; i<V; i++)
for (j=0; j<V; j++){
it++;
if (D[i][k] && D[k][j] && i!=j)
if (D[i][k]+D[k][j]<D[i][j] || D[i][j]==0)
D[i][j]=D[i][k]+D[k][j];
it++;}

for (i=0; i<V; i++)


{
for (j=0; j<V; j++) cout<<D[i][j]<<"\t";
cout<<endl;
}
}

int main()
{
setlocale(LC_ALL, "Rus");
clock_t start,end;
start=clock();
n=6;

ifstream f;
f.open("g6rar.txt");
int x;

for (int i = 0; i <= n-1; i++)


{
for (int j = 0; j <= n-1; j++)
{
f >> x;
GR[i][j] = x;
}
}
f.close();

/*
for (int i = 0; i <= n-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
cout <<"\t"<<GR[i][j];
}cout << endl;
}
getch();
*/
cout<<"\t Floyd: "<<endl;
cout<<"Matricea Drumurilor minime:"<<endl;
cout<<"--------------------------------------------"<<endl;
FU(GR, n);
cout<<"--------------------------------------------"<<endl;
end=clock();
printf("\n\nTimpul de executie este : %.8f \n",((double)(clock()-
start))/CLOCKS_PER_SEC);
cout << "Nr iteratii: "<<it;
}

6 virfuri rar:

6virfuri des:

15 virfuri rar:
15 virfuri des :

25 virfur rar:
25 virfuri des:

250 virfuri:
Exemplu
Algorit V Nr.iterati Timpul
mul i
Dijkstra 6 180 Rar:0.032
Des:0.032
Floyd 6 432 Rar:0.007
Des:0.008

Exemplu
Algorit V Nr.iterati Timpul
mul i
Dijkstra 15 3150 Rar:0.184
Des:0.193
Floyd 15 6750 Rar:0.036
Des:0.036

Exemplu
Algorit V Nr.iterati Timpul
mul i
Dijkstra 25 15000 Rar:0.458
Des:0.489
Floyd 25 31250 Rar:0.085
Des:0.179

Exemplu
Algorit U Nr.iterati Timpul
mul i
Dijkstra 250 15562500 37.564

Floyd 250 31250000 17.892


Dijkstra

Dijkstra/IT Timpul:

Floyd

Floyd/It Timpul
31250000

15562500

37,564 17,892

Iteratii Timp

Concluzie:
Efectuind lucrarea data ne-am facut cunoscuti cu Metoda
programrii dinamice.Si am analizat eficienta programarii
dinamice pentru diferite cazuri ale problemei. Implementind si
analizind algoritmele Dijksta si Floys am concluzionat ca acesti
algoritmi sunt rapizi si deci sunt algoritmi eficienti si foarte buni
pentru rezolvarea problemei de construire a arborelui de cost
minim.Observ ca dindui numarul de virufuri in cazul meu 6 15 25
si 250 in algoritmului Dijkstra numarul de iteratii atit in cazul cu
un numar de arce dens si rar ramine acelas doar ca incepe a varia
in dependenta dupa numarul de virfuri, timpul de executie creste
cu marirea numarului de virfuri.In cazul algoritmului Floyd
iteratiile nu depind de densitatea arcelor ci doar de numarul de
virfuri si semnificativ timpul de executie este mai mic decit la
Dijkstra in schimb numarul de iteratii este mult mai mare.