Documente Academic
Documente Profesional
Documente Cultură
Enunț
Se dau n orașe, numerotate de la 1 la n, și o listă cu m străzi bidirecționale (pe care se
poate circula în ambele sensuri), identificate prin cele două orașe-extremități și prin
lungime. Un comis-voiajor are misiunea de a livra colete în toate aceste orașe, cu
condiția să se întoarcă în orașul din care a plecat. El poate realiza asta în multe moduri,
însă îl interesează un drum de lungime minimă. Așadar, se cere determinarea unui
drum de lungime minimă, care să treacă prin fiecare oraș exact o singură dată, iar din
ultimul oraș vizitat să revină în primul.
Exemplu
De pe prima linie a fișierului comis.in se citesc n și m, numărul de orașe și respectiv
numărul de străzi. Pe fiecare dintre următoarele m linii se găsesc câte trei
numere x, y și z, cu semnificația că strada dintre orașele x și y are lungimea z.
5 8
1 2 20
1 5 60
1 4 30
2 4 30
4 3 70
2 3 40
4 5 30
5 3 30
comis.out
150
1 2 3 5 4 1
Soluție
Practic, ni se dă un graf neorientat cu costuri pe muchii, și trebuie să determinăm un
drum care trece prin toate nodurile grafului și se întoarce în nodul inițial, de cost minim.
Desigur, prin costul drumului ne referim la suma costurilor muchiilor din care acesta
este format. Folosind metoda backtracking, vom genera toate ciclurile hamiltoniene ale
grafului dat, și îl vom reține pe parcurs pe cel de cost minim.
0 20 0 30 60
20 0 40 30 0
0 40 0 70 30
30 30 70 0 30
60 0 30 30 0
De asemenea, în variabila n vom
reține lungimea traseului curent, iar în vectorul d orașele din care este compus acesta.
În plus, vom avea nevoie de o variabilă smin și de un vector dd pentru stocarea
traseului minim și a lungimii acestuia.
#include <bits/stdc++.h>
#define Dmax 15
using namespace std;
ifstream f("comis.in");
ofstream g("comis.out");
int n, m, a[Dmax][Dmax], x[Dmax], d[Dmax], dd[Dmax], smin =
INT_MAX, gasit, Suma;
void afis()
{
g << smin << "\n";
for(int i = 1; i <= n + 1; i ++)
g << dd[i] << " ";
}
void calculez()
{
gasit = 1;
Suma = 0;
d[1] = x[1];
for(int i = 2; i <= n; i ++)
{
d[i] = x[i];
Suma = Suma + a[x[i - 1]][x[i]];
}
d[n + 1] = x[1];
Suma = Suma + a[x[n]][x[1]];
if(Suma < smin)
{
smin = Suma;
memcpy(dd, d, sizeof(d));
}
}
int valid(int k)
{
if(a[x[k-1]][x[k]] == 0) return 0;
for(int i = 1; i < k; i ++)
if(x[k] == x[i]) return 0;
return 1;
}
void back(int k)
{
for(int i = 1; i <= n; i ++)
{
x[k] = i;
if(valid(k))
{
if(k == n)
{
if(a[x[k]][x[1]] > 0) calculez();
}
else back(k + 1);
}
}
}
int main()
{
int i, j, cost;
f >> n >> m;
while(m)
{
f >> i >> j >> cost;
a[i][j] = a[j][i] = cost;
m --;
}
x[1] = 1;
back(2);
if(!gasit) g << 0;
else afis();
return 0;
}