Sunteți pe pagina 1din 13

Ministerul Educaiei a Republicii Moldova

Universitatea Tehnic a Moldovei

Lucrare de laborator la
Matematica discret

Lucrare de laborator nr. 4-5

Tema: Drum minim (Alg. Ford si Belman-Kalaba)

A elaborat:

st. gr. TI-143


Fiodor Alexandru

A verificat:

Ceban Cheorghe

Chiinu 2015

1.

Scopul lucrrii:

Studierea algoritmilor de determinare a drumurilor minime ntr-un graf.


Elaborarea programelor de determinare a drumului minim ntr-un graf ponderat.
2.Sarcina de baz
1.
2.
3.

Elaborai procedura introducerii unui graf ponderat;


Elaborai procedurile determinrii drumului minim;
Realizai un program cu urmtoarele funcii:
introducerea grafului ponderat cu posibiliti de analiz sintactic i semantic;
determinarea drumului minim;
extragerea informaiei la display sau imprimant (valoarea drumului minim i succesiunea vrfurilor care formeaz
acest drum).

3.Listingul programului
//Lucrare de laborator Nr4.
//
Tema:Drum minim (Alg. Ford si Belman-Kalaba).
=
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
typedef struct list
{
int info;
struct list *adr;
}list;
list* pushList(list *prev_el, list *&head_el, int inf);
list** saveList(int n, list **adi_list);
void viewList(int n, list **adi_list);
int** matInitiala(int **mat_ini, int n, int &k, list **adi_list);
void drFord(int v_fin, int **mat_ini, int mat_res[100][100], int k, int val_init, int &lun_dr, int &nr_lin, int
n);
void algBK(int **mat_ini, int val_init, int v_start, int mat_res[100][100], int n, int k, int &lun_dr, int
&nr_lin);
void afisDrFord(int mat_res[100][100], int nr_lin);
void saveDrFord(int mat_res[100][100], int nr_lin, FILE *fp);
void saveFileList(int n, list **adi_list, FILE *fp);
void afisDrBK(int mat_res[100][100], int nr_lin);
void saveDrBK(int mat_res[100][100], int nr_lin, FILE *fp);
int matDr(int n, int m, int **mat_ini);
void cleanMem(int n, list **adi_list);
int main()
{
list **adi_list;
int n, k, v_pon, v_fin, val_init, lun_dr, nr_lin, v_start, opt, ex_max;
int **mat_ini, mat_res[100][100];
FILE *fp;
printf("Introduceti numarul de virfuri: ");
scanf("%d", &n);
adi_list = saveList(n, adi_list);

mat_ini = matInitiala(mat_ini, n, k, adi_list);


ex_max = matDr(n, k, mat_ini);
system("cls");
do
{
printf("||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
printf("|
Algoritmul Ford si Algoritmul Bellman Kalaba
|\n");
printf("||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
printf("|
1.Afisarea listei de adiacenta
|\n");
printf("|
2.Afisarea drumului minim(FORD)
|\n");
printf("|
3.Afisarea drumului maxim(FORD)
|\n");
printf("|
4.Afisarea drumului minim(Bellman Kalaba) |\n");
printf("|
5.Afisarea drumului maxim(Bellman Kalaba) |\n");
printf("|
0.Iesire
|\n");
printf("|
|\n");
printf("||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");
printf("Introduceti optiunea dorita: ");
fflush(stdin);
opt = getche();
switch(opt)
{
case '1':
printf("\n");
viewList(n, adi_list);
printf("Pentru a reveni apasa-ti orice tasta...");
fp = fopen("md_saveL4.txt", "w");
fputs("<=====Lista de adiacenta=====>\n", fp);
saveFileList(n, adi_list, fp);
fclose(fp);
getch();
system("cls");
break;
case '2':
printf("\nIntroduce-ti virful pina in care trebuie calculat dr.minim: ");
scanf("%d", &v_fin);
val_init = 2147483600;
drFord(v_fin, mat_ini, mat_res, k, val_init, lun_dr, nr_lin, n);
printf("\nLungimea drumului = %d\n", lun_dr);
printf("\n");
afisDrFord(mat_res, nr_lin);
printf("Pentru a reveni apasa-ti orice tasta...");
fp = fopen("md_saveL4.txt", "a");
fprintf(fp, "\nDrumul minim pina in virful %d (Alg.Ford):", v_fin);
fprintf(fp, "\nLungimea drumului = %d\n", lun_dr);
saveDrFord(mat_res, nr_lin, fp);
fclose(fp);
getch();
system("cls");
break;
case '3':
if(ex_max == 0)
{

printf("\nDrum maxim nu exista, pentru ca graful este cu circuite!");


printf("Pentru a reveni apasa-ti orice tasta...");
getch();
system("cls");
break;
}
printf("\nIntroduce-ti virful pina in care trebuie calculat dr.maxim: ");
scanf("%d", &v_fin);
val_init = -2147483600;
drFord(v_fin, mat_ini, mat_res, k, val_init, lun_dr, nr_lin, n);
printf("\nLungimea drumului = %d\n", lun_dr);
printf("\n");
afisDrFord(mat_res, nr_lin);
printf("Pentru a reveni apasa-ti orice tasta...");
fp = fopen("md_saveL4.txt", "a");
fprintf(fp, "\nDrumul maxim pina in virful %d (Alg.Ford):", v_fin);
fprintf(fp, "\nLungimea drumului = %d\n", lun_dr);
saveDrFord(mat_res, nr_lin, fp);
fclose(fp);
getch();
system("cls");
break;
case '4':
printf("\nIntroduce-ti virful din care trebuie calculat dr.minim: ");
scanf("%d", &v_start);
val_init = 2147483600;
algBK(mat_ini, val_init, v_start, mat_res, n, k, lun_dr, nr_lin);
printf("\nLungimea drumului = %d\n", lun_dr);
printf("\n");
afisDrBK(mat_res, nr_lin);
printf("Pentru a reveni apasa-ti orice tasta...");
fp = fopen("md_saveL4.txt", "a");
fprintf(fp, "\nDrumul minim din virful %d (Alg.B-K):", v_fin);
fprintf(fp, "\nLungimea drumului = %d\n", lun_dr);
saveDrBK(mat_res, nr_lin, fp);
fclose(fp);
getch();
system("cls");
break;
case '5':
if(ex_max == 0)
{
printf("\nDrum maxim nu exista, pentru ca graful este cu circuite!");
printf("Pentru a reveni apasa-ti orice tasta...");
getch();
system("cls");
break;
}
printf("\nIntroduce-ti virful din care trebuie calculat dr.maxim: ");
scanf("%d", &v_start);
val_init = -2147483600;
algBK(mat_ini, val_init, v_start, mat_res, n, k, lun_dr, nr_lin);

printf("\nLungimea drumului = %d\n", lun_dr);


printf("\n");
afisDrBK(mat_res, nr_lin);
printf("Pentru a reveni apasa-ti orice tasta...");
fp = fopen("md_saveL4.txt", "a");
fprintf(fp, "\nDrumul maxim din virful %d (Alg.B-K):", v_fin);
fprintf(fp, "\nLungimea drumului = %d\n", lun_dr);
saveDrBK(mat_res, nr_lin, fp);
fclose(fp);
getch();
system("cls");
break;
default:
system("cls");
}
}while(opt != '0');
return 0;
}
//Functia pentru adaugarea unui element intr-o lista cu parcurgerea de la inceput spre sfirsit
list* pushList(list *prev_el, list *&head_el, int inf)
{
list *tmp = (list *)malloc(sizeof(list));
tmp->info = inf;
tmp->adr = 0;
if(prev_el == 0)
head_el = tmp;
else
prev_el->adr = tmp;
prev_el = tmp;
return prev_el;
}
//Functia pentru introducerea listei de adiacenta
list** saveList(int n, list **adi_list)
{
int i, inf;
list *prev_el, *head_el;
adi_list = (list **)malloc(n * sizeof(list *));
for(i = 0; i < n; i++)
{
prev_el = head_el = 0;
printf("%d |", i + 1);
do
{
scanf("%d", &inf);
prev_el = pushList(prev_el, head_el, inf);
}while(inf != 0);
adi_list[i] = head_el;
}
return adi_list;
}

//Functia pentru afisarea listei de adiacenta


void viewList(int n, list **adi_list)
{
int i;
list *curr_el;
for(i = 0; i < n; i++)
{
curr_el = adi_list[i];
printf("%d |", i + 1);
while(curr_el != 0)
{
printf("%d ", curr_el->info);
curr_el = curr_el->adr;
}
printf("\n");
}
}
//Functia pentru salvarea listei de adiacenta
void saveFileList(int n, list **adi_list, FILE *fp)
{
int i;
list *curr_el;
for(i = 0; i < n; i++)
{
curr_el = adi_list[i];
fprintf(fp, "%d |", i + 1);
while(curr_el != 0)
{
fprintf(fp, "%d ", curr_el->info);
curr_el = curr_el->adr;
}
fprintf(fp, "\n");
}
}
//Functia pentru generarea matricei initiale cu care mai apoi vom lucra
int** matInitiala(int **mat_ini, int n, int &k, list **adi_list)
{
int i, v_pon;
list *curr_el;
k = 0;
mat_ini = (int **)malloc(k * sizeof(int *));
printf("Introduceti ponderile: \n");
for(i = 0; i < n; i++)
{
curr_el = adi_list[i];
while(curr_el->info != 0)
{
printf("P[%d, %d] = ", i + 1, curr_el->info);
scanf("%d", &v_pon);

mat_ini = (int **)realloc(mat_ini, (k + 1) * sizeof(int *));


mat_ini[k] = (int *)malloc(4 * sizeof(int));
mat_ini[k][0] = i + 1;
mat_ini[k][1] = curr_el->info;
mat_ini[k][2] = v_pon;
curr_el = curr_el->adr;
k++;
}
}
return mat_ini;
}
//Functia pentru gasirea drumurilor minime si maxime(Alg.B-K)
void algBK(int **mat_ini, int val_init, int v_start, int mat_res[100][100], int n, int k, int &lun_dr, int
&nr_lin)
{
int i, j, ii, con, n_v, min, max, nr_dr, nr_el, nr_ap, pos_v, aux;
int mat_luc[100][n];
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(i == j)
mat_luc[i][j] = 0;
else{
for(ii = 0; ii < k; ii++)
{
con = 0;
if(mat_ini[ii][0] == i + 1 && mat_ini[ii][1] == j + 1)
{
mat_luc[i][j] = mat_ini[ii][2];
con = 1;
break;
}
}
if(con == 0)
mat_luc[i][j] = val_init;
}
}
}
n_v = n;
for(i = 0; i < n; i++)
mat_luc[n_v][i] = mat_luc[i][n - 1];
con = 0;
if(val_init > 0)
{
do
{
n_v++;
for(j = 0; j < n - 1; j++)
{

min = val_init;
for(i = 0; i < n; i++)
if(i != j)
if(mat_luc[j][i] != val_init && mat_luc[n_v - 1][i] != val_init)
if(min > mat_luc[j][i] + mat_luc[n_v - 1][i])
min = mat_luc[j][i] + mat_luc[n_v - 1][i];
mat_luc[n_v][j] = min;
}
mat_luc[n_v][n - 1] = 0;
con = 1;
for(i = 0; i < n; i++)
if(mat_luc[n_v - 1][i] != mat_luc[n_v][i])
{
con = 0;
break;
}
}while(con != 1);
}else{
do
{
n_v++;
for(j = 0; j < n - 1; j++)
{
max = val_init;
for(i = 0; i < n; i++)
if(i != j)
if(mat_luc[j][i] != val_init && mat_luc[n_v - 1][i] != val_init)
if(max < mat_luc[j][i] + mat_luc[n_v - 1][i])
max = mat_luc[j][i] + mat_luc[n_v - 1][i];
mat_luc[n_v][j] = max;
}
mat_luc[n_v][n - 1] = 0;
con = 1;
for(i = 0; i < n; i++)
if(mat_luc[n_v - 1][i] != mat_luc[n_v][i])
{
con = 0;
break;
}
}while(con != 1);
}
lun_dr = mat_luc[n_v][v_start - 1];
nr_dr = 0;
nr_el = 1;
nr_lin = 0;
mat_res[nr_dr][1] = v_start;
do
{
do
{
nr_ap = 0;
pos_v = -1;

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


if(i != v_start - 1)
if(mat_luc[n_v][v_start - 1] - mat_luc[v_start - 1][i] == mat_luc[n_v]
[i])
{
nr_ap++;
if(pos_v == -1)
pos_v = i;
}
if(v_start != n)
if(nr_ap > 1)
{
nr_el++;
mat_res[nr_dr][nr_el] = pos_v + 1;
mat_res[nr_dr][0] = nr_el;
do
{
nr_lin++;
for(j = 0; j <= mat_res[nr_dr][0]; j++)
mat_res[nr_lin][j] = mat_res[nr_dr][j];
aux = pos_v + 1;
for(i = aux; i < n; i++)
{
if(mat_luc[n_v][v_start - 1] - mat_luc[v_start 1][i] == mat_luc[n_v][i])
break;
}
pos_v = i;
mat_res[nr_lin][mat_res[nr_dr][0]] = pos_v + 1;
nr_ap--;
}while(nr_ap != 1);
v_start = mat_res[nr_dr][mat_res[nr_dr][0]];
}else{
nr_el++;
v_start = pos_v + 1;
mat_res[nr_dr][nr_el] = pos_v + 1;
mat_res[nr_dr][0] = nr_el;
}
}while(v_start != n);
nr_dr++;
nr_el = mat_res[nr_dr][0];
v_start = mat_res[nr_dr][nr_el];
}while(nr_dr != nr_lin + 1);
}
//Functia pentru afisarea drumurilor gasite cu ajutorul Alg.Ford
void afisDrBK(int mat_res[100][100], int nr_lin)
{
int i, j;
for(i = 0; i <= nr_lin; i++)
{

for(j = 1; j <= mat_res[i][0]; j++)


printf("%d ", mat_res[i][j]);
printf("\n");
}
}
//Functia pentru salvarea drumurilor gasite cu ajutorul Alg.Ford
void saveDrBK(int mat_res[100][100], int nr_lin, FILE *fp)
{
int i, j;
for(i = 0; i <= nr_lin; i++)
{
for(j = 1; j <= mat_res[i][0]; j++)
fprintf(fp, "%d ", mat_res[i][j]);
fprintf(fp, "\n");
}
}
//Functia pentru cautarea drumurilor minime si maxime(Alg.Ford)
void drFord(int v_fin, int **mat_ini, int mat_res[100][100], int k, int val_init, int &lun_dr, int &nr_lin, int
n)
{
int vect_h[n + 1], v_e, i, nr_dr, nr_ap, nr_el, j, pos_v, c, aux, aux2;
vect_h[1] = 0;
for(i = 2; i <= n; i++)
vect_h[i] = val_init;
if(val_init > 0)
{
do
{
v_e = 0;
for(i = 0; i < k; i++)
{
if((vect_h[mat_ini[i][1]] - vect_h[mat_ini[i][0]]) > mat_ini[i][2])
{
vect_h[mat_ini[i][1]] = vect_h[mat_ini[i][0]] + mat_ini[i][2];
v_e++;
}
if(vect_h[mat_ini[i][1]] != val_init && (vect_h[mat_ini[i][1]] vect_h[mat_ini[i][0]]) == mat_ini[i][2])
{
mat_ini[i][3] = 1;
}
else
{
mat_ini[i][3] = 0;
}
}
}while(v_e != 0);

}else{
do
{
v_e = 0;
for(i = 0; i < k; i++)
{
if((vect_h[mat_ini[i][1]] - vect_h[mat_ini[i][0]]) < mat_ini[i][2])
{
vect_h[mat_ini[i][1]] = vect_h[mat_ini[i][0]] + mat_ini[i][2];
v_e++;
}
if((vect_h[mat_ini[i][1]] - vect_h[mat_ini[i][0]]) == mat_ini[i][2])
mat_ini[i][3] = 1;
else
mat_ini[i][3] = 0;
}
}while(v_e != 0);
}
lun_dr = vect_h[v_fin];
nr_dr = 0;
nr_el = 1;
nr_lin = 0;
mat_res[nr_dr][1] = v_fin;
do
{
do
{
nr_ap = 0;
pos_v = -1;
for(i = k - 1; i >= 0; i--)
if(v_fin == mat_ini[i][1] && mat_ini[i][3] == 1)
{
nr_ap++;
if(pos_v == -1)
pos_v = i;
}
if(v_fin != 1)
if(nr_ap > 1)
{
nr_el++;
mat_res[nr_dr][nr_el] = mat_ini[pos_v][0];
mat_res[nr_dr][0] = nr_el;
do
{
nr_lin++;
for(j = 0; j < mat_res[nr_dr][0]; j++)
mat_res[nr_lin][j] = mat_res[nr_dr][j];
aux = pos_v - 1;
for(i = aux; i >= 0; i--)
{

if(v_fin == mat_ini[i][1] && mat_ini[i][3] ==


1)
break;
}
pos_v = i;
mat_res[nr_lin][mat_res[nr_dr][0]] = mat_ini[pos_v][0];
nr_ap--;
}while(nr_ap != 1);
v_fin = mat_res[nr_dr][mat_res[nr_dr][0]];
}else{
nr_el++;
mat_res[nr_dr][nr_el] = mat_ini[pos_v][0];
mat_res[nr_dr][0] = nr_el;
v_fin = mat_ini[pos_v][0];
}
}while(v_fin != 1);
nr_dr++;
nr_el = mat_res[nr_dr][0];
v_fin = mat_res[nr_dr][nr_el];
}while(nr_dr != nr_lin + 1);
}
//Functia pentru afisarea drumurilor gasite cu ajutorul Alg.Ford
void afisDrFord(int mat_res[100][100], int nr_lin)
{
int i, j;
for(i = 0; i <= nr_lin; i++)
{
for(j = mat_res[i][0]; j >= 1; j--)
printf("%d ", mat_res[i][j]);
printf("\n");
}
}
//Functia pentru salvarea drumurilor gasite cu ajutorul Alg.Ford
void saveDrFord(int mat_res[100][100], int nr_lin, FILE *fp)
{
int i, j;
for(i = 0; i <= nr_lin; i++)
{
for(j = mat_res[i][0]; j >= 1; j--)
fprintf(fp, "%d ", mat_res[i][j]);
fprintf(fp, "\n");
}
}
//Functia pentru generarea matricei drumurilor
int matDr(int n, int m, int **mat_ini)

{
int i, j, k;
int mat_dr[n][n];
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
mat_dr[i][j] = 0;
for (i = 0; i < m; i++)
{
mat_dr[mat_ini[i][0] - 1][mat_ini[i][1] - 1] = 1;
}
for (k = 0; k < n; k++)
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (mat_dr[i][j] == 0)
mat_dr[i][j] = mat_dr[i][k] * mat_dr[k][j];
for (i = 0; i < n; i++)
if(mat_dr[i][i] == 1)
return 0;
return 1;
}
//Eliberarea memoriei dinamice ocupate de toate elementele programului
void cleanMem(int n, list **adi_list)
{
int i;
list *curr_el, *prev_el;
for(i = 0; i < n; i++)
{
curr_el = adi_list[i];
while(curr_el != 0)
{
//prev_el = curr_el;
prev_el = curr_el->adr;
free(curr_el);
curr_el = prev_el;
}
}
free(adi_list);
}

Concluzie: Efectuind aceasta lucrare , neam familiarizat cu algoritmul aflarii drumului minim.Acest
algoritm ne permite de a afla drumul minim intre orce doua vurfuri prin metoda lui Ford
si prin metoda lui Bellman-Kalaba.Acest algoritm se aplic pe larg n practic de exemplu laproectarea oselelor sau a diferitor tipuri de comunicaii,deci studiind teoretic acum
acest algoritm pe viitotr e posibil s-l aplicm pentru un caz real.