Advertisement
Guest User

aff

a guest
Apr 30th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.26 KB | None | 0 0
  1. //--------------------------------------------------------------
  2. // NOMES DOS RESPONSÁVEIS: Andrei Oliveira e Chá
  3. //--------------------------------------------------------------
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <conio.h>
  8. #include <malloc.h>
  9.  
  10. // ######### ESCREVA O NROUSP DO PRIMEIRO INTEGRANTE AQUI
  11. char* nroUSP1() {
  12.     return("0000000");
  13. }
  14.  
  15. // ######### ESCREVA O NROUSP DO SEGUNDO INTEGRANTE AQUI (OU DEIXE COM ZERO)
  16. char* nroUSP2() {
  17.     return("0000000");
  18. }
  19.  
  20.  
  21. // elemento das listas de adjacência e de resposta
  22. typedef struct estr {
  23.         int v; // elemento
  24.     int peso; // custo (não precisa ser usado na resposta)
  25.         struct estr *prox;
  26. } NO;
  27.  
  28. // vertices do grafo (salas) - use este tipo ao criar o grafo
  29. typedef struct
  30. {
  31.        int flag; // para uso na busca em largura e profundidade, se necessario
  32.        bool aberto; // vale true se a sala em questao esta aberta
  33.        NO* inicio;
  34. } VERTICE;
  35.  
  36.  
  37. // funcao principal
  38. NO *caminho(int N, int A, int *ijpeso, int *aberto, int inicio, int fim, int chave);
  39.  
  40. void Dijkstra(int N, int A, int *ijpeso, int inicio, int *dist, int *ant) //Função para fazer o caminho de dijkstra
  41. {
  42.     //INICIALIZAR A MATRIZ!
  43.     int matriz[N][N]; //matriz de AxA arestas, onde o valor na aresta matriz[i][j] é o peso desta aresta;
  44.     for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) matriz[i][j] = 999999999;//Inicialização da matriz, recebendo infinito (999999999) como resposta
  45.     //PREENCHER A MATRIZ!
  46.     //A matriz de entrada é a matriz representada pelo ponteiro ijpeso, e tem tamanho 3A, ordenada em ternas {origem, dest, peso};
  47.     int cont = 0; //contador para o preenchimento da matriz;
  48.     int orig = 0; //variável para guardar a origem
  49.     int dest = 0; //variável para guardar o destino
  50.     int peso = 0; //variável para guardar o peso
  51.  
  52.     while(cont < 3*A) //Enquanto o contador não chegar até o final do vetor...
  53.     {
  54.         orig = ijpeso[cont]; //A origem é sempre o primeiro número da terna
  55.         peso = ijpeso[cont]; //O peso da aresta é sempre o terceiro número da terna
  56.         cont++; //incrementa o contador que marca se a informação é a origem, o destino, ou o peso...
  57.         dest = ijpeso[cont]; //O destino é sempre o segundo número da terna;
  58.         cont++; //incrementa o contador, marcando que o próximo número é o peso;
  59.         peso = ijpeso[cont]; //O peso da aresta é sempre o terceiro número da terna
  60.         matriz[orig][dest] = peso; //Preenche a matriz com a aresta [origem, destino] e peso [peso]
  61.         cont++; //Incrementa o contador, indicando que o próximo número é o começo de outra terna que indica a origem e destino da aresta além de seu peso...
  62.     }
  63.     bool proc[N]; //Marca se um vértice já teve seu custo mínimo determinado pelo algoritmo...
  64.     for(int i = 0; i < N; i++) //Para todos os vértices...
  65.     {
  66.         dist[i] = matriz[inicio][i];  //dist será o peso a aresta do vértice inicio até o vértice i
  67.         proc[i] = false;
  68.         ant[i] = -1;
  69.     }
  70.     dist[inicio] = 0; //A distância até o vértice próprio é zero;
  71.     proc[inicio] = true; //O primeiro vértice já teve seu custo mínimo determinado...
  72.     ant[inicio] = -1; //Início não tem anterior;
  73.     int vert = inicio; //Primeiro vértice a ser verificado;
  74.     while(true){ // repetir pra sempre...
  75.  
  76.         int menor = 999999999; //Menor distância não foi calculada ainda, ou seja, é infinita;
  77.  
  78.         //Para cada vértice i adjacente a ...
  79.         for(int i = 0; i < N; i++) {
  80.             if(!proc[i] && dist[i] < menor) {//Se a distância entre o início e este vértice i for menor que a menor distância descoberta até agora...
  81.                 vert = i; //O próximo vértice a ser olhado será este, o de menor distância
  82.                 menor = dist[i]; //Atualiza a menor distância;                
  83.             }
  84.         }
  85.  
  86.  
  87.         if(vert == -1) break; //Se não existe nenhum caminho novo a ser olhado, para o algoritmo
  88.  
  89.         proc[vert] = true; // Marca que a distância mínima do início até o vértice vert foi analisada
  90.         for(int i = 0; i < N; i++){//Para todos os vértices...
  91.             if(dist[i] > (dist[vert] + matriz[vert][i])){ //Se a distância atual de inicio até i for maior que a distância de inicio até o vértice atual mais a distância entre o vértice atual e o vértice i...
  92.                 dist[i] = dist[vert] + matriz[vert][i]; //atualiza a nova menor distância de inicio até i como sendo a distância entre inicio e vert mais a distância entre vert e i;
  93.             }
  94.         }
  95.         vert = -1; //Vértice a ser olhado;
  96.     }
  97. }
  98.  
  99. //------------------------------------------
  100. // O EP consiste em implementar esta funcao
  101. // e outras funcoes auxiliares que esta
  102. // necessitar
  103. //------------------------------------------
  104. NO *caminho(int N, int A, int *ijpeso, int *aberto, int inicio, int fim, int chave)
  105. {
  106.     NO* resp;
  107.     resp = NULL;
  108.  
  109.     //ENCONTRAR O CAMINHO MÍNIMO == DIJKSTRA!
  110.     int dist[N]; //Variável que guarda as distâncias
  111.     int ant[N]; //Marca o vértice anterior utilizado para se chegar no vértice ant[i];
  112.     Dijkstra(N, A, ijpeso, inicio, dist, ant);
  113.     if(dist[fim] == 999999999) //Se a distância até o final for infinita...
  114.         return resp; //Retorna uma lista vazia: caminho inexistente;
  115.     //Todos os custos mínimos calculados!
  116.     //Verificar agora se o caminho precisa de chave ou não!
  117.     int verif = fim; //Variável para verificar o caminho de mínimo custo realizado;
  118.     bool precisaChave = false; //Variável que determina se o caminho precisa ou não de chave
  119.     while(ant[verif] != 1 || ant[verif] == verif){ //Enquanto a sala verificada tiver anterior... (ou seja, existir anterior...);
  120.         if(!aberto[verif])//Se a sala sendo verificada não estiver aberta...
  121.             precisaChave = true; //Marca este estado;
  122.         verif = ant[verif]; //Define para verificação o vértice o anterior do vértice atual sendo verificado
  123.     }
  124.     //Construir o caminho!
  125.     if(precisaChave) { //Se o caminho mínimo antes encontrado precisa de chave...
  126.         //Devemos usar o caminho já encontrado de custo mínimo até a sala chave...
  127.         //... e depois recalcular um caminho de custo mínimo da sala chave até a sala fim;
  128.         verif = chave; //Começar a construir o caminho de volta, iniciando da sala chave...
  129.         while(ant[verif] != 1 || ant[verif] == verif) //Enquanto o caminho da chave até o inicio tiver anterior...
  130.         {
  131.             if(!aberto[verif]) resp = NULL; //Não existe um caminho destrancado até a sala CHAVE;
  132.             NO* novo = (NO*) malloc(sizeof(NO)); //Novo nó que guardará este vértice no caminho;
  133.             novo->v = verif; //Coloca o vértice atual no nó novo do caminho;
  134.             novo->prox = resp; //Atualiza que o próximo nó do caminho é o caminho até agora
  135.             resp = novo; //Atualiza o primeiro nó do caminho de volta;
  136.             verif = ant[verif];
  137.         }
  138.         //Com o caminho de chave até início construído...
  139.         Dijkstra(N, A, ijpeso, chave, dist, ant); //Calcula o caminho de custo mínimo da sala chave até a sala fim;
  140.         verif = fim; //Começar a construir o caminho de volta, iniciando da sala fim...
  141.         while(ant[verif] != 1 || ant[verif] == verif) //Enquanto o caminho do fim até a sala chave tiver anterior...
  142.         {
  143.             NO* novo = (NO*) malloc(sizeof(NO)); //Novo nó que guardará este vértice no caminho;
  144.             novo->v = verif; //Coloca o vértice atual no nó novo do caminho;
  145.             novo->prox = resp; //Atualiza que o próximo nó do caminho é o caminho até agora
  146.             resp = novo; //Atualiza o primeiro nó do caminho de volta;
  147.             verif = ant[verif];
  148.         }
  149.     }
  150.     else{
  151.         verif = fim; //Começar a construir o caminho de volta, iniciando da sala fim...
  152.         while(ant[verif] != 1 || ant[verif] == verif) //Enquanto o caminho do fim até a sala chave tiver anterior...
  153.         {
  154.             NO* novo = (NO*) malloc(sizeof(NO)); //Novo nó que guardará este vértice no caminho;
  155.             novo->v = verif; //Coloca o vértice atual no nó novo do caminho;
  156.             novo->prox = resp; //Atualiza que o próximo nó do caminho é o caminho até agora
  157.             resp = novo; //Atualiza o primeiro nó do caminho de volta;
  158.             verif = ant[verif];
  159.         }
  160.     }
  161.     return resp;
  162. }
  163.  
  164.  
  165.  
  166. //---------------------------------------------------------
  167. // use main() para fazer chamadas de teste ao seu programa
  168. //---------------------------------------------------------
  169. int main() {
  170.  
  171.  
  172.     // aqui vc pode incluir codigo de teste
  173.  
  174.     // exemplo de teste trivial
  175.     int N=9; // grafo de 3 vértices 1..3
  176.     int aberto[] = {0,1,1,1,1,1,1,1,1}; // todos abertos
  177.     int inicio=7;
  178.     int fim=4;
  179.     int chave=6;
  180.     int A = 18;
  181.     int ijpeso[]={1,2,30,1,3,20,2,1,30,2,6,20,2,7,30,6,2,20,6,7,10,
  182.         7,6,10,
  183.         7,2,30,
  184.         7,3,80,
  185.         7,9,80,
  186.         3,1,20,
  187.         3,7,80,
  188.         3,4,20,
  189.         4,3,20,
  190.         4,9,80,
  191.         9,4,80,
  192.         9,7,80};
  193.  
  194.     // o EP sera testado com uma serie de chamadas como esta
  195.     NO* teste = NULL;
  196.     teste = caminho(N, A, ijpeso, aberto, inicio, fim, chave);
  197.     while(teste){
  198.         printf("<= V: %i", teste->v);
  199.         teste = teste->prox;
  200.     }
  201.     return 0;
  202. }
  203.  
  204. // por favor nao inclua nenhum código abaixo da função main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement