Lab 4 Apa
Lab 4 Apa
Lab 4 Apa
Raport
privind efectuarea
lucrării de laborator nr.4
Chișinău 2018
Cuprin
Scopul lucrării.......................................................................................................................................3
Realizarea..............................................................................................................................................4
Anexa A................................................................................................................................................8
Anexa B...............................................................................................................................................14
Scopul lucrării
Sarcina lucrării
Să se realizeze analiza empirică a algoritmilor Dijkstra și Floyd pentru
determinarea celor mai scurte drumuri dintr-un graf.
Realizarea
Noțiuni teoretice
Floyd
Fie G = <V, A> un graf orientat, unde V este mulţimea vârfurilor şi A este
mulţimea arcelor. Fiecărui arc i se asociază o lungime nenegativă. Vom presupune că
vârfurile sunt numerotate de la 1 la n şi că matricea L dă lungimea fiecărui arc:
Principiul optimalităţii este valabil: dacă cel mai scurt drum de la i la j trece prin
varful k, atunci porţiunea de drum de la i la k, cât şi cea de la k la j, trebuie să fie, de
asemenea, optime. Construim o matrice D care să conţină lungimea celui mai scurt
drum între fiecare pereche de vârfuri. Algoritmul de programare dinamică
iniţializează pe D cu L.
Dk[i, j] = min(Dk-1[i, j], Dk-1[i, k] Dk-1[k, j])
Dijkstra
Notăm cu C mulţimea vârfurilor disponibile (candidaţii) şi cu S mulţimea
vârfurilor deja selectate. În fiecare moment, S conţine acele vârfuri a căror distanţă
minimă de la sursă este deja cunoscută, în timp ce mulţimea C conţine toate celelalte
vârfuri. La început, S conţine doar vârful sursă, iar în final S conţine toate vârfurile
grafului. La fiecare pas, adăugam în S acel vârf din C a cărui distanţă de la sursă este
cea mai mică.
Cazul favorabil
120000
100000
80000
60000
40000
20000
0
10 100 500
Dijkstra Floyd
Cazul mediu
2500000
2000000
1500000
1000000
500000
0
10 100 500
Dijkstra Floyd
Cazul defavorabil
2000000
1800000
1600000
1400000
1200000
1000000
800000
600000
400000
200000
0
10 100 500
Dijkstra Floyd
Concluzii
În urma efectuării lucrării de laborator nr.4, s-au dezvoltat noi abilități în
prelucrarea algoritmilor Floyd și Dijkstra pentru aflarea costului dumului minim într-
un graf neorientat.
Conform programului utilizat pentru determinarea numărului de iterații, s-a
dovedit că algoritmul Floyd este mai eficient, precum avem mai puține iterații. Un
avantaj foarte mare al algoritmului dat este că are doar 3 cicluri și poate fi cu ușurință
implementat în cod.
În urma analizii empirice s-a determinat că algoritmul Floyd ar fi unul mai
eficient în cazurile favorabile și random, în comparație cu Dijkstra.
Anexa A
Pseudocod Floyd
Pseudocod Dijkstra
Listingul programului
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define max 500
#define INF INT_MAX
using namespace std;
unsigned long long MS[max][max], MV[max][max], MVdij[max][max],
MVfloid[max][max], n, parent[max], visited[max],
path[max], disvec[max][max];
int count1 = 0, count2 = 0, tmpi, u, possition = 0, start, finish;
void RESET() {
count1 = 0;
count2 = 0;
for (int i = 0; i<n; i++) {
parent[i] = 0;
visited[i] = 0;
for (int j = 0; j<n; j++) {
MVdij[i][j] = MV[i][j];
MVfloid[i][j] = MV[i][j];
}
}
}
//cazul defavorabil
void nr_virf_defavorabil() {
cout << "Numarul de virfuri: ";
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
if (j > i) {
MS[i][j] = rand() % 1000;
}
else if (i > j) {
MS[i][j] = MS[j][i];
}
}
}
void costurile_defavorabil() {
MV[i][j] = MS[i][j];
}
else
MV[i][j] = INF;
}
}
RESET();
}
//cazul favorabil
void nr_virf_favorabil() {
cout << "Numarul de virfuri: ";
cin >> n;
MV[i][j] = MS[i][j];
}
else
MV[i][j] = INF;
}
}
RESET();
}
//cazul mediu
void nr_virf_mediu() {
cout << "Numarul de virfuri: ";
cin >> n;
MV[i][j] = MS[i][j];
}
else
MV[i][j] = INF;
}
}
RESET();
}
void DIJKSTRA() {
int distance[max],disvec[max][max],visited[max];
cout << "Introduceti 2 virfuri unde doriti sa cautati" << endl;
cout << "Din "; cin >> start; cout << "In "; cin >> finish;
for (int ji = 0; ji < n; ji++) {
for (int i = 0; i < n; i++) {
distance[i] = INF;
visited[i] = 0;
}
distance[start - 1] = 0;
int st = 0;
for (int i = 0; i < n; i++) {
disvec[st][i] = distance[i];
}
for (int i = 0; i < n - 1; i++) {
int min = INF;
for (int i = 0; i < n; i++) {
if (!visited[i] && distance[i] <= min) {
min = distance[i];
tmpi = i;
count1++;
}
}
u = tmpi;
visited[u] = 1;
for (int i = 0; i < n; i++) {
if (!visited[i] && MVdij[u][i] && distance[u] != INF && distance[u] +
MVdij[u][i] < distance[i]) {
distance[i] = distance[u] + MVdij[u][i];
count1++;
}
}
st++;
for (int i = 0; i < n; i++) {
disvec[st][i] = distance[i];
count1++;
}
}
int k = finish - 1;
path[possition] = finish - 1;
while (path[possition] != start - 1) {
if (disvec[st][k] == disvec[st - 1][k]) {
st--;
}
else {
for (int j = 0; j < n; j++) {
if (disvec[st][k] == disvec[st - 1][j] + MVdij[j][k]) {
path[++possition] = j;
k = j;
st--;
break;
}
}
}
}
}
cout << "Drumul minin de la " << start << " pina la " << finish << " este " <<
distance[finish - 1] << "." << endl;
cout << "Numarul de iteratii : " << count1 << endl;
}
void FLOYD() {
int start, finish;
cout << "Introduceti 2 virfuri pentru a afla drumul minim" << endl;
cout << "Din "; cin >> start; cout << "In "; cin >> finish;
for (int k = 0; k<n; k++)
for (int i = 0; i<n; i++)
for (int j = 0; j<n; j++) {
count2++;
if (MVfloid[i][k] && MVfloid[k][j] && i != j)
if (MVfloid[i][k] + MVfloid[k][j]<MVfloid[i][j] || MVfloid[i][j] ==
0) {
MVfloid[i][j] = MVfloid[i][k] + MVfloid[k][j];
count2++;
}
}
cout << "Drumul minim de la " << start << " pina la " << finish << " este " <<
MVfloid[start - 1][finish - 1] << "." << endl;
cout << "Numarul de iteratii : " << count2 << endl;
}
int main() {
double t1, t2;
int ChooseMenu;
int x;
x: while (true) {
system("cls");
cout << "1. Cazul favorabil." << endl
<< "2. Cazul mediu." << endl
<< "3. Cazul defavorabil." << endl
<< "0. Exit." << endl;
cout << endl << ">>> ";
cin >> ChooseMenu;
system("cls");
switch (ChooseMenu) {
case 1: {
while (true) {
system("cls");
cout << "1. Introduceti numarul de virfuri." << endl
<< "2. Algoritmul Floyd." << endl
<< "3. Algoritmul Dijkstra." << endl
<< "0. Meniul principal." << endl;
cout << endl << ">>> ";
cin >> ChooseMenu;
system("cls");
switch (ChooseMenu) {
case 1: {
nr_virf_favorabil();
costurile_favorabil();
break;
}
case 2: {
FLOYD();
break;
}
case 3: {
DIJKSTRA();
break;
}
case 0: {
RESET();
goto x;
}
default: {
cout << "Optiune gresita" << endl;
break;
}
}
system("pause");
system("cls");
}
case 2: {
while (true) {
system("cls");
cout << "1. Introduceti numarul de virfuri." << endl
<< "2. Algoritmul Floyd." << endl
<< "3. Algoritmul Dijkstra." << endl
<< "0. Meniul principal." << endl;
cout << endl << ">>> ";
cin >> ChooseMenu;
system("cls");
switch (ChooseMenu) {
case 1: {
nr_virf_mediu();
costurile_mediu();
break;
}
case 2: {
FLOYD();
break;
}
case 3: {
DIJKSTRA();
break;
}
case 0: {
RESET();
goto x;
}
default: {
cout << "Optiune gresita" << endl;
break;
}
}
system("pause");
system("cls");
}
case 3: {
while (true) {
system("cls");
cout << "1. Introduceti numarul de virfuri." << endl
<< "2. Algoritmul Floyd." << endl
<< "3. Algoritmul Dijkstra." << endl
<< "0. Meniul principal." << endl;
cout << endl << ">>> ";
cin >> ChooseMenu;
system("cls");
switch (ChooseMenu) {
case 1: {
nr_virf_defavorabil();
costurile_defavorabil();
break;
}
case 2: {
FLOYD();
break;
}
case 3: {
DIJKSTRA();
break;
}
case 0: {
RESET();
goto x;
}
default: {
cout << "Optiune gresita" << endl;
break;
}
}
system("pause");
system("cls");
}
case 0: {
return 0;
}
default: {
cout << "Optiune gresita" << endl;
break;
}}}}}
system("pause");
system("cls");}}
Anexa B
Cazul favorabil
Cazul mediu