Di62028

distancia_cidades3.c

Aug 29th, 2020 (edited)
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.87 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include <stdbool.h>
  6. #include <limits.h>
  7.  
  8. int dijkstra(int qt_cidades, int graph[qt_cidades][qt_cidades], int src, int destino_index, char cidades[][21]);
  9.  
  10. typedef struct{
  11.     char cidade1[21];
  12.     char cidade2[21];
  13.     int distancia;
  14. } Rota;
  15.  
  16.  
  17. int verifica_se_esta_no_vetor(char vetor[][21], char palavra[], int tamanho_do_vetor){
  18.  
  19.     for (int i = 0; i < tamanho_do_vetor; i++){
  20.         if (strcmp(palavra, vetor[i]) == 0){
  21.             return 1;
  22.         }
  23.     }
  24.  
  25.     return 0;
  26. }
  27.  
  28. int procura_caminhos_entre_cidades(Rota rotas_ptr[], char cidade1[], char cidade2[], int arestas){
  29.  
  30.     for(int i = 0; i < arestas; i++){
  31.         if (strcmp((rotas_ptr + i)->cidade1, cidade1) == 0 && strcmp((rotas_ptr + i)->cidade2, cidade2) == 0){
  32.             return (rotas_ptr + i)->distancia;
  33.         }
  34.     }
  35.  
  36.     return 0;
  37. }
  38.  
  39. void impime_matriz(int qt_cidades, int matriz[qt_cidades][qt_cidades], int tamanho_linha, int tamanho_coluna){
  40.     printf("\n\n");
  41.     for (int i = 0; i < tamanho_linha; i++){
  42.         for(int j = 0; j < tamanho_coluna; j++){
  43.             printf("  %d  ", matriz[i][j]);
  44.         }
  45.         printf("\n");
  46.     }
  47. }
  48.  
  49.  
  50. int main(int argc, char *argv[]){
  51.     printf("Digite o nome do arquivo de entrada: ");
  52.     char nome_do_arquivo[100];
  53.     scanf("%s", &nome_do_arquivo[0]);
  54. //  char nome_do_arquivo[] = "teste.txt";
  55.  
  56.     /// Abre o arquivo e verifica se foi ok
  57.     FILE *arquivo;
  58.     arquivo = fopen(nome_do_arquivo, "r");
  59.     if (arquivo == NULL){
  60.         printf("Erro na abertura do aqruivo\n");
  61.         return(1);
  62.     }
  63.  
  64.     int arestas = 0;
  65.  
  66.     /// Armazena a primeira linha do arquivo de entrada
  67.     fscanf(arquivo, "%d", &arestas);
  68.  
  69.     Rota *rotas_ptr = (Rota*) malloc(arestas * sizeof(Rota));
  70.  
  71.     /// Continua lendo o arquivo com as entradas e armazenando os valores
  72.     for(int i = 0; i < arestas; i++){
  73.  
  74.         fscanf(arquivo, "%s", (rotas_ptr + i)->cidade1);
  75.         fscanf(arquivo, "%s", (rotas_ptr + i)->cidade2);
  76.         fscanf(arquivo, "%d", &(rotas_ptr + i)->distancia);
  77.  
  78.     }
  79.  
  80.     int qt_cidades = 0;
  81.     char cidades[1000][21]; // Número máximo de cidades: 1000
  82.  
  83.     /// Preenche um vetor com os nomes das cidades
  84.  
  85.     ///     Para as cidades à esquerda no arquivo
  86.     for(int i = 0; i < arestas; i++){
  87.         char cid[21];
  88.  
  89.         strcpy(cid, (rotas_ptr + i)->cidade1);
  90.  
  91.         /// Verifica se a cidade já foi adicionada ao vetor
  92.         int v = verifica_se_esta_no_vetor(cidades, cid, arestas);
  93.         if (v == 0){
  94.             strcpy(cidades[qt_cidades], cid);
  95.             qt_cidades++;
  96.         }
  97.     }
  98.  
  99.     ///     Para as cidades à direita no arquivo
  100.     for(int i = 0; i < arestas; i++){
  101.         char cid[21];
  102.  
  103.         strcpy(cid, (rotas_ptr + i)->cidade2);
  104.  
  105.         /// Verifica se a cidade já foi adicionada ao vetor
  106.         int v = verifica_se_esta_no_vetor(cidades, cid, arestas);
  107.         if (v == 0){
  108.             strcpy(cidades[qt_cidades], cid);
  109.             qt_cidades++;
  110.         }
  111.     }
  112.  
  113.     /// Lê as cidades de origem e destino e atribui o valor
  114.     char origem[21] = "";
  115.     char destino[21] = "";
  116.  
  117.     fscanf(arquivo, "%s", origem);
  118.     fscanf(arquivo, "%s", destino);
  119.  
  120.     // Cria a matriz/ grafo
  121.     int (*grafo)[qt_cidades] = malloc(qt_cidades * qt_cidades * sizeof(grafo[0][0]));
  122.  
  123.     // Preenche a matriz/ grafo inicialmente com zeros
  124.     for (int i = 0; i < qt_cidades; i++){
  125.         for(int j = 0; j < qt_cidades; j++){
  126.             grafo[i][j] = 0;
  127.         }
  128.     }
  129.  
  130.     /// Este FOR preenche a matriz/ grafo com as distâncais entre as cidades (caminhos)
  131.     for (int i = 0; i < qt_cidades; i++){
  132.         char linha[21];
  133.         strcpy(linha, cidades[i]);
  134.  
  135.         for(int j = 0; j < qt_cidades; j++){
  136.             char coluna[21];
  137.             strcpy(coluna, cidades[j]);
  138.  
  139.             /// Procura a distâncias entre todas as cidades e preenche todas as
  140.             /// posições da matriz (tanto superior quanto inferior)
  141.             int dist = procura_caminhos_entre_cidades(rotas_ptr, linha, coluna, arestas);
  142.  
  143.             if (grafo[i][j] < dist)
  144.                 grafo[i][j] = dist;
  145.  
  146.             if (grafo[j][i] < dist)
  147.                 grafo[j][i] = dist;
  148.  
  149.         }
  150.     }
  151.  
  152.     /// Identifica a cidade de origem e a cidade de destino por meio de índices.
  153.     /// Esses índices serão passados para a função Dijkstra, que já funcionava
  154.     /// de tal maneira
  155.     int origem_index = -1;
  156.     int destino_index = -1;
  157.     for (int i = 0; i < qt_cidades; i++){
  158.         if (strcmp(origem, cidades[i]) == 0){
  159.             origem_index = i;
  160.         }
  161.         if (strcmp(destino, cidades[i]) == 0){
  162.             destino_index = i;
  163.         }
  164.     }
  165.     if (origem_index == -1){
  166.         printf("\n Cidade de origem não encontrada!");
  167.         return 2;
  168.     }
  169.     if (destino_index == -1){
  170.         printf("\n Cidade de destino não encontrada!");
  171.         return 3;
  172.     }
  173.  
  174.     /// Chama a função dijkstra e imprime a menor distância
  175.     printf("Menor percurso: ");
  176.     int resposta = dijkstra(qt_cidades, grafo, origem_index, destino_index, cidades);
  177.     printf("%s\n", cidades[destino_index]);
  178.     printf("Distancia total: %d Km", resposta);
  179.  
  180.     /// Fecha
  181.     fclose(arquivo);
  182.     return 0;
  183. }
  184.  
  185.  
  186. /*
  187.     Abaixo, o algoritmo de Dijkstra. Tal algoritmo foi retirado do site
  188.     Geeks for Geeks, e pode ser acessado pelo link:
  189.     https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
  190.  
  191.     Originalmente sua implementação não previa informar o menor caminho (os nomes das
  192.     cidades), apenas a menor distância, além de estar em C++. Com algumas modirficações,
  193.     foi adicionada tal funcionalidade e compatibilidade com C.
  194. */
  195.  
  196. // A C++ program for Dijkstra's single source shortest path algorithm.
  197. // The program is for adjacency matrix representation of the graph
  198.  
  199. //#include <limits.h>
  200. //#include <stdio.h>
  201.  
  202. // Number of vertices in the graph
  203. //#define V 5
  204.  
  205. // A utility function to find the vertex with minimum distance value, from
  206. // the set of vertices not yet included in shortest path tree
  207. int minDistance(int dist[], bool sptSet[], int V)
  208. {
  209.     // Initialize min value
  210.     int min = INT_MAX, min_index;
  211.  
  212.     for (int v = 0; v < V; v++){
  213.         if (sptSet[v] == false && dist[v] <= min){
  214.             min = dist[v];
  215.             min_index = v;
  216.         }
  217.     }
  218.     return min_index;
  219. }
  220.  
  221. // A utility function to print the constructed distance array
  222. void printSolution(int dist[], int V)
  223. {
  224.     printf("\n\nVertex \t\t Distance from Source\n");
  225.     for (int i = 0; i < V; i++)
  226.         printf("%d \t\t %d\n", i, dist[i]);
  227. }
  228.  
  229. // Function that implements Dijkstra's single source shortest path algorithm
  230. // for a graph represented using adjacency matrix representation
  231. int dijkstra(int qt_cidades, int graph[qt_cidades][qt_cidades], int src, int destino_index, char cidades[][21])
  232. {
  233.     int V = qt_cidades;
  234.     int dist[V]; // The output array. dist[i] will hold the shortest
  235.     // distance from src to i
  236.  
  237.     bool sptSet[V]; // sptSet[i] will be true if vertex i is included in shortest
  238.     // path tree or shortest distance from src to i is finalized
  239.  
  240.     // Initialize all distances as INFINITE and stpSet[] as false
  241.     for (int i = 0; i < V; i++)
  242.         dist[i] = INT_MAX, sptSet[i] = false;
  243.  
  244.     // Distance of source vertex from itself is always 0
  245.     dist[src] = 0;
  246.  
  247.     char vetor_menor_percurso[V][21];
  248.     int vetor_menor_percurso_dist[V];
  249.     int auxiliar2 = 0;
  250.  
  251.     // Find shortest path for all vertices
  252.     for (int count = 0; count < V - 1; count++) {
  253.         // Pick the minimum distance vertex from the set of vertices not
  254.         // yet processed. u is always equal to src in the first iteration.
  255.         int u = minDistance(dist, sptSet, V);
  256.  
  257.         // Mark the picked vertex as processed
  258.         sptSet[u] = true;
  259.  
  260.  
  261.         int auxiliar = 0;
  262.         // Update dist value of the adjacent vertices of the picked vertex.
  263.         for (int v = 0; v < V; v++){
  264.  
  265.             // Update dist[v] only if is not in sptSet, there is an edge from
  266.             // u to v, and total weight of path from src to v through u is
  267.             // smaller than current value of dist[v]
  268.             if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
  269.                 && dist[u] + graph[u][v] < dist[v]){
  270.                 dist[v] = dist[u] + graph[u][v];
  271.             }
  272.  
  273.             /// Inicialmente esse código só mostrava a distância total final,
  274.             /// então foram necessárias algumas modificações para que
  275.             /// ele também fosse registrando as cidades do menor caminho
  276.             if (auxiliar == destino_index){
  277.                 strcpy(vetor_menor_percurso[auxiliar2], cidades[u]);
  278.                 vetor_menor_percurso_dist[auxiliar2] = dist[destino_index];
  279.                 auxiliar2++;
  280.             }
  281.             auxiliar++;
  282.  
  283.         }
  284.  
  285.     }
  286.  
  287.     int i = 0;
  288.     do{
  289.         printf("%s ", vetor_menor_percurso[i]);
  290.         i++;
  291.     }while(vetor_menor_percurso_dist[i-1] != dist[destino_index]);
  292.  
  293. //  // print the constructed distance array
  294. //  printSolution(dist, int V);
  295.  
  296.     return dist[destino_index];
  297.  
  298. }
Add Comment
Please, Sign In to add comment