//método que busca todos os caminhos possíveis para um determinado destino private void BuscarCaminhos(int idOrigem, int idDestino, int indiceInicial) //parâmetros: id cidade origem, id cidade destino, índice inicial para percorrer na matriz de adjacências { //se a origem for igual ao destino, por se tratar de um método recursivo com a origem mudando de acordo com as cidades percorridas //empilhamos o id da cidade destino na pilha //adicionamos o caminho na lista de caminhos possíveis, clonando-o já que o reutilizamos para achar outros caminhos if (idOrigem == idDestino) { caminho.Empilhar(idDestino); caminhosPossiveis.Add(caminho.Clone()); } //caso a origem seja diferente do destino else { //variável que será utilizada para a realização de verificações, recebendo os índices das cidades int c = -1; //até achar uma adjacência (conexão entre cidades) ou acabar as cidades da linha da matriz for (int i = indiceInicial; i < adjacencias.GetLength(0); i++) { //se há uma conexão e esta cidade não foi percorrida anteriormente neste mesmo caminho encontrado if (adjacencias[idOrigem, i] != 0 && cidadesPercorridas[i] == false) { //"c" recebe o id da cidade a ser percorrida c = i; break; } } //não é possível chegar ao destino no caminho encontrado ou todas as possibilidades de caminho por esta cidade já foram encontradas if (c == -1) { //ele voltou para a cidade origem, portanto já encontrou todos os caminhos if (caminho.EstaVazia()) { percorreuTodosOsCaminhosPossiveis = true; } //se ainda existem opções, volta uma posição(uma cidade) para procurar outra possibilidade else { Retornar(idOrigem, idDestino); } } else { //definimos que a cidade foi percorrida cidadesPercorridas[idOrigem] = true; //empilhamos o id da cidade usada no método caminho.Empilhar(idOrigem); //buscamos um novo caminho a partir da última cidade encontrada BuscarCaminhos(c, idDestino, 0); } } }
public void encontrarCaminho(int idCidadeDestino, int idCidadeOrigem, int idAtual) { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //CALCULA TODOS OS CAMINHOS POSSIVEIS E OS ARMAZENA NO LIST todosCaminho if (idCidadeDestino == idCidadeOrigem) // Caso a cidade origem seja igual a cidade destino { caminhoPossivel.Empilhar(idCidadeDestino); todosCaminhos.Add(caminhoPossivel.Clone()); achou = true; } else { for (int i = 0; i <= 22; i++) { if (caminhos[idAtual, i] != null && !visitadados.Contains(caminhos[idAtual, i])) // Verifica se o caminho atual já foi percorrido ou seja diferente { // de null, caso isso ocorra ele continua com a busca de caminhos caminhoPossivel.Empilhar(idAtual); if (i == idCidadeDestino) // caso a cidadeDestino seja encontrada { caminhoPossivel.Empilhar(i); todosCaminhos.Add(caminhoPossivel.Clone()); //CaminhoPossivel é armazenado em todosCaminhos while (!caminhoPossivel.EstaVazia()) // Desempilha o caminhoPossivel para tentar encontrar ou caminho { caminhoPossivel.Desempilhar(); } visitadados.Add(caminhos[idAtual, i]); // Adiciona o caminho atual nos visitados para que ele não seja percorrido de novo achou = true; encontrarCaminho(idCidadeDestino, idCidadeOrigem, idCidadeOrigem); // O método é chamado novamente de forma recurssiva } // para verificar se existe outro caminho possivel else { PilhaLista <int> caminhoPossivelAux = caminhoPossivel.Clone(); caminhoPossivelAux.Desempilhar(); encontrarCaminho(idCidadeDestino, idCidadeOrigem, i); // Caso o caminhoAtual não seja igual ao caminhoDestino caminhoPossivel = caminhoPossivelAux; // } } if (i == 22) // caso não tenha sido achodo nenhum caminho e o for tenha chegado ao fim . { while (!caminhoPossivel.EstaVazia()) // limpa a variavel caminhoPossivel desempilhando ela { caminhoPossivel.Desempilhar(); } } } } }
//evento que efetivamente chama os métodos que desenham as cidades no mapa e o caminho entre elas //permite a utilização de "Graphics" de pbMapa private void pbMapa_Paint(object sender, PaintEventArgs e) { Graphics gr = e.Graphics; DesenharCidade(cidades.Raiz, gr); if (caminhoASerMostrado != null && caminhosPossiveis.Count > 0) { DesenharCaminho(caminhoASerMostrado.Clone(), e.Graphics); } }
public int distancia(PilhaLista <int> caminho) // Calcula a distancia total de um caminho { int distanciaTotal = 0; int[] caminhoVet = new int[caminho.Tamanho()]; PilhaLista <int> caminhoAux = caminho.Clone(); int i = 0; while (!caminhoAux.EstaVazia()) { caminhoVet[i] = caminhoAux.Desempilhar(); // Preenche o vetor caminhoVet com os caminhos da pilha caminhoAux i++; } for (i = caminho.Tamanho() - 1; i > 0; i--) { distanciaTotal += caminhos[caminhoVet[i], caminhoVet[i - 1]].Distancia; // calcula a distancia total do caminho } return(distanciaTotal); }
//===========================================================================================================================================// //========MÉTODO USADO PARA TRAÇAR A MELHOR ROTA ENTRE AS CIDADES SELECIONADAS===============================================================// private void melhorCaminhoPaint(Graphics g)// PRINTA NO MAPA OS MENOR CAMINHO DE UMA CIDADE ORIGEM PARA UMA CIDADE DESTINO { pbMapa.Refresh(); pbMapa.Paint += new System.Windows.Forms.PaintEventHandler(this.pbMapa_Paint); Pen p = new Pen(Color.Blue, 4); PilhaLista <int> menorCaminhoAux = menorCaminho.Clone(); int[] caminhoVet = new int[menorCaminhoAux.Tamanho()]; Queue <int> Xaux = new Queue <int>(); Queue <int> Yaux = new Queue <int>(); Queue <int> X = new Queue <int>(); Queue <int> Y = new Queue <int>(); int i = 0; while (!menorCaminhoAux.EstaVazia()) { caminhoVet[i] = menorCaminhoAux.Desempilhar(); i++; } for (i = 0; i < menorCaminho.Tamanho() - 1; i++) { X.Enqueue(cidade[caminhoVet[i]].CoordenadaX); Y.Enqueue(cidade[caminhoVet[i]].CoordenadaY); Xaux.Enqueue(cidade[caminhoVet[i + 1]].CoordenadaX); Yaux.Enqueue(cidade[caminhoVet[i + 1]].CoordenadaY); g.DrawLine(p, (pbMapa.Width * X.Dequeue()) / 4096, (pbMapa.Height * Y.Dequeue()) / 2048, (pbMapa.Width * Xaux.Dequeue()) / 4096, (pbMapa.Height * Yaux.Dequeue()) / 2048); } }
private void BtnBuscar_Click(object sender, EventArgs e) //Método chamado no evento click do btnBuscar { MessageBox.Show("Buscar caminhos entre cidades selecionadas"); //Mensagem mandada ao usuário ao clique do botão btnBuscar pbMapa.Refresh(); //Método que "limpa" o mapa, apagando o caminho que possivelmente estava sendo exibido antes dataGridView1.Rows.Clear(); //Método que apaga as linhas populadas com o caminho escolhido anteriormente peo usuário dataGridView2.Rows.Clear(); //Método que apaga as linhas populadas com o caminho escolhido anteriormente peo usuário dataGridView2.Columns.Clear(); //Método que deleta as colunas antes exibidas no dataGridView PilhaLista <Caminho> aux2 = new PilhaLista <Caminho>(); //Declaração e instanciação da pilha de caminhos que guardará todos os caminhos encontrados que levarão ao destino desejado PilhaLista <Caminho> caminhos = new PilhaLista <Caminho>(); //Declaração e instanciação da pilha de caminhos que guardará todos os possíveis caminhos, cada rota que possivelmente levará ao destino escolhido PilhaLista <Caminho> aux = new PilhaLista <Caminho>(); //Declaração e instanciação da pilha de caminhos que inicialmente guardará todos os caminhos que tem como início a origem determinada int qtdCaminhos = 0; //Variável que guarda o número de caminhos encontrados, usada mais tarde na instanciação do vetor de caminhos int atual = lsbOrigem.SelectedIndex; //Variável que guarda o índice da cidade escolhida pelo usuário como origem bool acabouCaminho = false; //Variável que guarda 'true' se a cidade destino foi alcançada ou 'false' caso não bool[] visitados = new bool[arvore.QuantosDados]; //Vetor do tipo boolean que guardará true sempre que a cidade correspondente foi verificada/visitada e false em caso contrário int nCidades = 0; //Variável que guarda o número de cidades que o caminho com maior cidades contém int menorCaminho = Int32.MaxValue; //Variável que guarda a menor distância encontrada int distancia; //Variável que guarda a distância percorrida no caminho atualmente analisado string[] nomeMelhor = new string[arvore.QuantosDados]; //Vetor de string que guarda os nomes das cidades contidas no melhor caminho encontrado vetorCaminhos = new object[100]; int qtd = arvore.QuantosDados; //Variável que guarda a quantidade de cidades contidas na árvore criada while (!acabouCaminho) //Loop definido pela verificação do encontro ou não de um caminho { distancia = 0; bool empilhou = false; //Variável boolean que verifica se algum caminho foi empilhado com a origem atual for (int c = 0; c < qtd; c++) //Loop que se repete pelo número de cidades existentes { if (matriz[atual, c] != default(int)) //Verificação: se o valor da posição atual da matriz é diferente de 0, ou seja, se entre os índices(cidades) definidos existe uma rota { aux.Empilhar(new Caminho(atual, c, matriz[atual, c])); //Caso exista uma rota entre essas cidades, essa será empilhada na pilha empilhou = true; //Atribuição de valor true para a variável 'empilhou', já que um posssível caminho foi encontrado } } if (!empilhou) //Verificação: se nenhum possível caminho foi encontrado desta vez { if (!aux.EstaVazia()) //se a pilha aux não estiver vazia { while (!aux.EstaVazia() && !caminhos.EstaVazia() && aux.OTopo().Origem != caminhos.OTopo().Destino) //se a pilha "aux" e a pilha "caminhos" não estiverem vazia e a origem do topo de "aux" for diferente da origem do topo de "caminhos" { caminhos.Desempilhar(); //Caso nada tenha sido empilhado, devemos desempilhar da pilha caminhos até que a origem do caminho no topo da pilha aux seja igual ao destino do caminho do topo da pilha caminhos } } } if (aux.EstaVazia()) //Verificação: se a pilha aux não tiver elementos, então não é possível prosseguir a procura por um caminho { acabouCaminho = true; //Portanto, para sair do loop, a variável acabouCaminho recebe true } else //Caso a pilha aux não esteja vazia, a busca por um caminho deve presseguir { Caminho um = aux.Desempilhar(); //Variável local que guarda o caminho analisado atualmente if (um.Destino == lsbDestino.SelectedIndex) //Verificação: se um caminho foi encontrado { caminhos.Empilhar(um); //Empilha na pilha "caminhos" if (caminhos.Tamanho() > nCidades) //Se o tamanho da pilha "caminhos" atual, a quantidade de cidades, for maior do que a maior quantidades de cidades em um caminho ("nCidades") { nCidades = caminhos.Tamanho(); //A quantidade máxima de cidades em um caminho recebe a quantidade de cidades no caminho atual } aux2 = caminhos.Clone().Inverter(); //A pilha "aux2" recebe o clone da pilha "caminhos" invertida if (!aux.EstaVazia()) //se a pilha aux não estiver vazia { while (!aux.EstaVazia() && !caminhos.EstaVazia() && aux.OTopo().Origem != caminhos.OTopo().Destino) //se a pilha "aux" e a pilha "caminhos" não estiverem vazia e a origem do topo de "aux" for diferente da origem do topo de "caminhos" { caminhos.Desempilhar(); //Caso nada tenha sido empilhado, devemos desempilhar da pilha caminhos até que a origem do caminho no topo da pilha aux seja igual ao destino do caminho do topo da pilha caminhos } } caminhos.Empilhar(um); atual = um.Destino; //variável atual recebe o destino do topo de "aux" int i = 0; //Variável que armazena o indíce dos vetores dataGridView1.RowCount++; //Aumenta a quantidade de linhas do DataGridView dataGridView1.ColumnCount = nCidades + 1; //A quantidade de colunas do DataGridView recebe o maior número de cidades de todos os caminhos possíveis double?[] cod = new double?[arvore.QuantosDados]; //Representa um vetor que armazena os códigos de todas as cidades do caminho atual em ordem string[] nomes = new string[arvore.QuantosDados]; //Representa um vetor que armazena os nomes de todas as cidades do caminho atual em ordem Caminho c = new Caminho(); //Representa a rota atual while (!aux2.EstaVazia()) //Enquanto a pilha "aux2" estiver vazia { c = aux2.Desempilhar(); //A rota atual recebe o topo de "aux2" e desempilha esta Cidade cid = arvore.BuscaPorDado(new Cidade(c.Origem)); //Representa a cidade de origem da rota atual nomes[i] = cid.Nome; //Armazena o nome desta cidade na posição atual do vetor de nomes cod[i] = cid.Cod; //Armazena o codigo desta cidade na posição atual do vetor de códigos distancia += c.Distancia; //A distância total do caminho soma a distância da rota atual dataGridView1[i++, dataGridView1.RowCount - 1].Value = cid.Nome; //"Escreve" o nome da cidade atual no DataGridView } nomes[i] = (arvore.BuscaPorDado(new Cidade(c.Destino))).Nome; //Guarda o nome da última cidade no vetor de nomes cod[i] = (arvore.BuscaPorDado(new Cidade(c.Destino))).Cod; //Guarda o codigo da última cidade no vetor de códigos dataGridView1[i, dataGridView1.RowCount - 1].Value = nomes[i]; //"Escreve" o nome da última cidade no DataGridView if (distancia < menorCaminho) //Verificação: se a distância percorrida nesse caminho for menor que a menor distância já encontrada { menorCaminho = distancia; //A variável menorCaminho passa a guardar a distância atual melhorCaminho = cod; //Como a distância atual é a menor encontrada, o melhor caminho passa a ser o atual, portanto o valor do vetor de códigos melhorCaminho recebe o vator de códigos atual nomeMelhor = new string[i]; //Instanciação do vetor que guarda os nomes das cidades que o caminho atual contém nomeMelhor = nomes; //Atribuição do vetor de nomes das cidades percorridas neste caminho ao vetor que guarda nomes de cidades pelas quais passa o melhor caminho } //Caso não seja menor, nada acontece, para que a variável contenha o menor valor de todos corretamente vetorCaminhos[qtdCaminhos] = cod; //Atribuição do vetor de códigos atual à posição atual do vetorCaminhos, para que este guarde os códigos das cidades percorridas nesse caminho qtdCaminhos++; //Acrescentamos uma unidade à variável qtdCaminhos } else { caminhos.Empilhar(um); //Ao acharmos uma possível rota, ela é guardada na pilha de possíveis rotas atual = um.Destino; //Mudamos o valor da variável atual, que passará a guardar a origem do caminho que será verificado posteriormente } } } if (qtdCaminhos == 0) //Caso a quantidade de caminhos encontrados seja zero, não existe uma rota entre as cidades escolhidas, portanto, alertamos o usuário { MessageBox.Show("Não existe caminho!"); //Mensagem exibida ao usuário para alertá-lo da inexistência de caminhos } else //Caso a quantidade de caminhos encontrados não seja zero, achamos pelo menos um caminho { ExibirMelhorCaminho(nomeMelhor); //Chamada de método para exibir o melhor caminho encontrado } }
/* * Método que utiliza backtraking e pilhas para encontrar todos os caminhos entre dois pontos. Armazena todos os caminhos * em uma lista e determina qual posição guarda o menor. * @params dois inteiros sendo que a origem a cidade de onde estamos saindo e o destino a cidade onde queremos chegar. */ private void AcharCaminhos(int origem, int destino) { listaCaminhos = new List <PilhaLista <Caminho> >(); int menorDistancia = int.MaxValue, disAtual = 0; PilhaLista <Caminho> caminhoAtual = new PilhaLista <Caminho>(); PilhaLista <Caminho> aux = new PilhaLista <Caminho>(); bool[] jaPassou = new bool[23]; for (int i = 0; i < 23; i++) { jaPassou[i] = false; } int atual = origem; bool acabou = false; while (!acabou) { int tamanhoAnterior = aux.Tamanho(); for (int i = 0; i < 23; i++) { if (grafo[atual, i] != 0 && !jaPassou[i]) { aux.Empilhar(new Caminho(atual, i, grafo[atual, i])); } } if (!aux.EstaVazia() && tamanhoAnterior == aux.Tamanho()) { Caminho cam = caminhoAtual.Desempilhar(); disAtual -= cam.Distancia; jaPassou[cam.IdDestino] = true; } if (aux.EstaVazia()) { acabou = true; } else { Caminho c = aux.Desempilhar(); while (!caminhoAtual.EstaVazia() && caminhoAtual.OTopo().IdDestino != c.IdOrigem) { Caminho cam = caminhoAtual.Desempilhar(); disAtual -= cam.Distancia; jaPassou[cam.IdDestino] = false; } caminhoAtual.Empilhar(c); disAtual += c.Distancia; if (c.IdDestino != destino) { jaPassou[c.IdOrigem] = true; atual = c.IdDestino; } else { listaCaminhos.Add(caminhoAtual.Clone()); if (disAtual < menorDistancia) { menor = listaCaminhos.Count - 1; menorDistancia = disAtual; } if (aux.EstaVazia()) { acabou = true; } else { Caminho retorno = aux.Desempilhar(); while (!caminhoAtual.EstaVazia() && caminhoAtual.OTopo().IdDestino != retorno.IdOrigem) { Caminho cam = caminhoAtual.Desempilhar(); disAtual -= cam.Distancia; jaPassou[cam.IdDestino] = false; } caminhoAtual.Empilhar(retorno); jaPassou[retorno.IdDestino] = true; disAtual += retorno.Distancia; while (retorno.IdDestino == destino && !acabou) { listaCaminhos.Add(caminhoAtual.Clone()); if (disAtual < menorDistancia) { menor = listaCaminhos.Count - 1; menorDistancia = disAtual; } if (!aux.EstaVazia()) { retorno = aux.Desempilhar(); while (!caminhoAtual.EstaVazia() && caminhoAtual.OTopo().IdDestino != retorno.IdOrigem) { Caminho cam = caminhoAtual.Desempilhar(); disAtual -= cam.Distancia; jaPassou[cam.IdDestino] = false; } caminhoAtual.Empilhar(retorno); disAtual += retorno.Distancia; } else { acabou = true; } } atual = retorno.IdDestino; } } } } }