Codice:
Codice: Seleziona tutto
/// gcc -Wall -g 3d.c -o xx
#include <stdio.h>
#include <stdlib.h>
#define N 6
#define INF 10000
#define ASCII 97
void init_distanze(int distanze[N]);
void azzera_nodo(int grafo[N][N],int start);
int cerca_minimi(int distanze[N],int grafo[N][N],int start);
//-----------------------------------------------------------------------------------------------------
// cerca nodo con distanza minima
// nodo contrassegnato con -2 anche se presenta distanza minima
// non può essere usato perchè già stato usato
int cerca_minimi(int distanze[N],int grafo[N][N],int start)
{
int min,tmp,tmp2, i;
for (i=1; i<N; i++)
{
if (distanze[i]<INF && grafo[i][i]!=-2 )
{
tmp=distanze[i];
tmp2=i;
min=tmp;
break;
}
}
for (i=1; i<N; i++)
{
if ( (distanze[i]<tmp) && grafo[i][i]!=-2 )
{
tmp=distanze[i];
if (tmp<min)
{
min=tmp;
tmp2=i;
}
}
}
return tmp2;
}
//-----------------------------------------------------------------------------------------------------
// il nodo di partenza ha già visitato altri nodi,quindi va scartato
// e non deve più essere considerato
void azzera_nodo(int grafo[N][N],int start)
{
int i;
for (i=0; i<N; i++)
grafo[i][start]=-1;
grafo[start][start]=-2;
}
//-----------------------------------------------------------------------------------------------------
// inizializzazione distanze: tutti i nodi tranne il primo hanno
// distanza infinita. Io li imposto a 10000 perchè non so gestire infinito in C
// nodo zero impostato a zero
void init_distanze(int distanze[N])
{
int i;
for (i=0; i<N; i++)
distanze[i]=INF;
distanze[0]=0;
}
//-----------------------------------------------------------------------------------------------------
int main(void) {
int grafo[N][N]={{-1,5,6,1,-1,-1},
{5,-1,-1,1,1,7 },
{6,-1,-1,-1,1,1},
{1,1,-1,-1,3,-1},
{-1,1,1,3,-1,3 },
{-1,7,1,-1,3,-1}};
int distanze[N];
int nodi_precedenti[N]={0};
int i,k,temp,min;
int start=0;
int z=0;
char s[20];
init_distanze(distanze);
for (i=0; i<N-1; i++) // scansiona per N-1 volte i nodi
{
for (k=0; k<N; k++)
{
if (grafo[start][k]>=0) // scansiona nodo per vedere a cosa è connesso
{
temp=distanze[start]+grafo[start][k];
if (temp<distanze[k])
{
distanze[k]=temp;
nodi_precedenti[k]=start;
}
}
}
azzera_nodo(grafo,start);
min=cerca_minimi(distanze,grafo,start);
start=min;
}
//-----------------------------------------------------------------------------------------------------
// stampo percorso partendo da nodo 0 (o nodo A)
s[z]=(N-1)+ASCII;
for (i=N-1; i!=nodi_precedenti[i]; i=nodi_precedenti[i])
{
z++;
s[z]=nodi_precedenti[i]+ASCII;
}
for (i=z; i>=0; i--)
printf ("%c",s[i]);
puts("");
return 0;
}
1) Il grafo deve essere orientato? Alcuni articoli dicono di si, altri no. A parte che può essere "misto", cioè alcuni archi orientati e altri no.
per esempio un senso unico in un percorso deve per forza essere orientato.
2) io ho implementato il grafo con una matrice di adiacenze, ma se per piccoli grafi va bene, salendo di numero diventa un problema di
memoria essendo pari a NODI*NODI. Cosa potrebbe essere un alternativa ? Le liste. Ci avevo pensato, ma a conti fatti, visto che devi scomodare l'allocazione dinamica non so fino a che punto il gioco valga la candela.
Oltretutto le liste le devi scorrere tutte, non come gli array che hanno indici. Logicamente non c'è un meglio, va valutato caso per caso, ma mi piacerebbe avere consigli.
3) mi pare di aver letto che nell'algoritmo di Dijkstra si usa anche una coda di priorità (che al momento non so bene padroneggiare), ma non so a che scopo.
4) come posso gestire il concetto infinito in C? c'e' qualche scappatoia?
Comunque il codice (a meno di sviste e bug sfuggiti) funziona.
Se qualcuno mi desse info aggiuntive, io sono qui, grazie.