Algoritmul
lui Roy-Floyd
Fie G=(V, E) un graf neorientat, unde V are n elemente
(n noduri) si E are m elemente (m
muchii) memorat prin matricea ponderilor. Se cere ca pentru doua noduri
x,y citite sa se determine lungimea minima a lantului de la x la y.
Astfel:
|
Initial matricea ponderilor pentru
nodurile 1 si 4 va retine 10. Se observa ca lantul
1,2,3,4 determina o suma a costurilor mai mica: 2+3+1=6. Lungime minima a lantului de la 1 la 4 este 6.
Algoritmul:
-se genereaza
matricea ponderilor:
|
0 2 pinf 10 pinf 2 0 3 pinf pinf pinf 3 0 1 8 10 pinf 1 0 pinf pinf pinf 8 pinf 0 |
Unde pinf
reprezinta plus infinit
-se incearca
pentru oricare pereche de noduri i,j sa se
obtina “drumuri” mai scurte prin noduri intermediare k (kÎ1…n).
Acest lucru se
determina comparand “lungimea” lantului a[i,j] cu lungimea lantului care trece
prin k si daca:
a[i,j] > a[i,k]+a[k,j] atunci se atribuie: a[i,j] ¬ a[i,k]+a[k,j]
Astfel generarea matricii drumurilor optime se realizeaza cu
urmatoarea secventa:
for(int
k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]>a[i][k]+a[k][j])
a[i][j]=a[i][k]+a[k][j];
Se obtine:
|
0 2 5 6 13 2 0 3 4 11 5 3 0 1 8 6 4 1 0 9 13 11 8 9 0 |
In
continuare, dupa determinarea matricii lanturilor optime, pentru doua noduri
citite x, y se cere sa se reconstituie un lant optim de la x la y (pot fi mai
multe solutii).
Solutie:
-se determina daca exista un lant de la x
la y (ar putea sa nu existe un astfel de lant daca graful nu este conex):
cand a[x,y] ¹¥
-se descompune “drumul” de la x la y prin k
atunci cand: a[x][y]=a[x][k]+a[k][y];
-
pentru
un astfel de algoritm se utilizeaza strategia Divide et Impera
Iata o
solutie:
#include<fstream.h>
#include<conio.h>
const
pinf=1000; //pentru
plus infinit
int
a[20][20],n,m;
void
citire_cost()
{fstream f;
int i,j,x,y,c;
f.open("roy.in",ios::in);
if(f)
cout<<"deschiderea a
reusit";
else
cout<<"eroare la
deschidere!";
cout<<endl;
f>>n>>m;
//initializare matrice
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
a[i][j]=0;
else
a[i][j]=pinf;
for(i=1;i<=m;i++)
{f>>x>>y>>c;
a[x][y]=a[y][x]=c;}
}
void
afisare_mat()
{for(int
i=1;i<=n;i++)
{for(int j=1;j<=n;j++)
if(a[i][j]==pinf)
cout<<"pinf ";
else
cout<<a[i][j]<<"
";
cout<<endl;}
}
void
genarare_matrice_drumuri_optime()
{for(int
k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]>a[i][k]+a[k][j])
a[i][j]=a[i][k]+a[k][j];
}
void
descompun_drum(int i,int j) //realizeaza
descompunerea portiunii de la i la j prin k
{int
g=0,k=1;
while(k<=n&&!g)
{if(i!=k&&j!=k)
if(a[i][j]==a[i][k]+a[k][j])
{descompun_drum(i,k);
descompun_drum(k,j);
g=1;} //g
marcheaza daca se poate realiza descompunerea
k++;
}
if(!g)
cout<<j<<" "; //cand
“drumul” nu mai poate fi descompus afisez extremitatea finala
}
void
scriu_drum(int nodini,int nodfin) // functia
primeste ca parametri cele doua noduri pt care se determina optimul
{if(a[nodini][nodfin]<pinf)
{cout<<"lantul de la "<<nodini<<" la
"<<nodfin<<" are lungimea "<<a[nodini][nodfin];
cout<<endl<<"un drum
optim este: "<<endl;
cout<<nodini<<" ";
descompun_drum(nodini,nodfin); // apeleaza functia care afiseaza efectiv lantul
}
else
cout<<"nu exista drum de la
"<<nodini<<" la "<<nodfin;
}
void main()
{clrscr();int
x,y;
citire_cost();
cout<<endl<<"matricea
ponderilor "<<endl;
afisare_mat();
genarare_matrice_drumuri_optime();
cout<<endl<<"matricea
drumurilor optime "<<endl;
afisare_mat();
cout<<endl<<"Se
determina drumul minim intre varfurile x si y "<<endl;
cout<<"x=";
cin>>x;
cout<<"y=";
cin>>y;
scriu_drum(x,y);
getch();
}
Probleme
propuse:
▪
Intre
n statii spatiale se stabilesc trasee. Se cunosc traseele directe intre perechi
de statii si distanta dintre ele. Sa se determine drumul minim intre doua
statii date stiind ca nu pot fi doua statii pare una dupa cealalta. Sa se afiseze drumul de la statia x la
statia y.
▪
Reteaua
de strazi a unui oras este reprezentata prin nodurile intersectii ale orasului.
Din intersectiile A si B pleaca doi pietoni spre intersectiile x, respectiv y.
Ei conosc bine orasul si merg spre destinatie pe drumul minim. Stabiliti daca
traseele au trecut prin puncte comune si care sunt aceste intersectii.
Determinati daca exista intersectiile in care s-au intalnit.
▪
Intr-o tabara, elevii au n puncte de plecare (cantina, corturile,
stejarul cel batran etc.). Initial,
deplasarea intre oricare doua puncte se face intr-un timp t, insa organizatorii
au amplasat m obstacole pe traseele dintre aceste puncte. Cu fiecare obstacol
care trebuie depasit, elevii pierd 30 de secunde. Pe
un traseu pot fi mai multe obstacole. Elevii vor sa ajunga
din punctul X in punctul Y, pe drumul cel mai scurt. Scrieti
un program care citeste n, X, Y. Apoi m perechi de
puncte intre care sunt amplasate obstacole si afiseaza
drumul cel mai rapid intre X si Y.