void ExibirMelhorCaminho(PilhaLista <Caminho> caminho, int cor) { dgvMelhorCaminho.Rows.Clear(); dgvMelhorCaminho.RowCount = 1; dgvMelhorCaminho.ColumnCount = 10; var pilhaCopia = caminho.Copia(); Caminho caminhoAtual = null; PilhaLista <Caminho> pilhaCopiaAux = new PilhaLista <Caminho>(); while (!pilhaCopia.EstaVazia()) { pilhaCopiaAux.Empilhar(pilhaCopia.Desempilhar()); } corAtual = 2; melhorCaminho = pilhaCopiaAux.Copia(); int c = 0; while (!pilhaCopiaAux.EstaVazia()) { caminhoAtual = pilhaCopiaAux.Desempilhar(); dgvMelhorCaminho.Rows[0].Cells[c].Value = dadosCidade[caminhoAtual.IdCidadeOrigem].NomeCidade; c++; } dgvMelhorCaminho.Rows[0].Cells[c].Value = dadosCidade[caminhoAtual.IdCidadeDestino].NomeCidade; }
private int quantasCidades; //variavel que guarda quantas cidades existem no grafo atual public Grafo(string nomeDoArquivo, int numeroDeCidades) { var arquivo = new StreamReader(nomeDoArquivo); matrizAdjacente = new Caminho[numeroDeCidades, numeroDeCidades]; //cria a matriz com o numero de cidades existentes quantasCidades = numeroDeCidades; var linha = arquivo.ReadLine(); //para cada linha lida while (linha != null) { //atribui os valores do arquivo texto a variaveis locais int codOrigem = int.Parse(linha.Substring(inicioCodOrigem, tamanhoCodOrigem)); int codDestino = int.Parse(linha.Substring(inicioCodDestino, tamanhoCodDestino)); int distancia = int.Parse(linha.Substring(inicioDistancia, tamanhoDistancia)); int tempo = int.Parse(linha.Substring(inicioTempo, tamanhoTempo)); int custo = int.Parse(linha.Substring(inicioCusto, tamanhoCusto)); //quando é possivel ir de uma cidade a outra, guardamos os dados do caminho na posição //respectiva na matriz adjacente matrizAdjacente[codOrigem, codDestino] = new Caminho(codOrigem, codDestino, distancia, tempo, custo); //armazenamos o caminho matrizAdjacente[codDestino, codOrigem] = new Caminho(codDestino, codOrigem, distancia, tempo, custo); //armazenamos o caminho inverso para que seja possivel ir e voltar entre as cidades linha = arquivo.ReadLine(); } }
void ExibirCaminhos(PilhaLista <PilhaLista <Caminho> > caminhos) { dgvCaminhos.Rows.Clear(); dgvCaminhos.RowCount = caminhos.Tamanho(); dgvCaminhos.ColumnCount = 10; var pilhaCopia = caminhos.Copia(); Color[] cores = { Color.Black, Color.Blue, Color.Red, Color.Green, Color.Orange, Color.Purple, Color.Navy, Color.Brown }; for (int i = 0; i < dgvCaminhos.RowCount; i++) { PilhaLista <Caminho> pcAtual = caminhos.Desempilhar(); var aux = new PilhaLista <Caminho>(); while (!pcAtual.EstaVazia()) { aux.Empilhar(pcAtual.Desempilhar()); } int c = 0; Caminho cAtual = null; dgvCaminhos.Rows[i].DefaultCellStyle.ForeColor = Color.White; dgvCaminhos.Rows[i].DefaultCellStyle.BackColor = cores[i]; while (!aux.EstaVazia()) { cAtual = aux.Desempilhar(); dgvCaminhos.Rows[i].Cells[c].Value = dadosCidade[cAtual.IdCidadeOrigem].NomeCidade; c++; } dgvCaminhos.Rows[i].Cells[c].Value = dadosCidade[cAtual.IdCidadeDestino].NomeCidade; } caminhosDescobertos = pilhaCopia; pbMapa.Invalidate(); }
/** * Tratamento do clique do botão de buscar caminhos. * Primeiramente, são realizadas verificações para garantir que as Listboxs estão devidamente selecionadas. * Se sim, é criado um vetor com o nome de cada cidade presente nos arquivos textos (de forma ordenada). * Em seguida, são definidas quais são as cidades de origem e destino selecionadas pelo usuário, de acordo com o índice das Listboxs. * Feito isso, o programa percorre a lista de cidades para encontrar o Id de tais cidades e chama o método de buscar caminhoe e melhor caminho. * Por fim, os resultados são armazenados em listas que serão passadas como parâmetro dos métodos de exibição. */ private void BtnBuscar_Click(object sender, EventArgs e) { try { int idCidadeOrigem = -1, idCidadeDestino = -1; LerCidadesSelecionadas(ref idCidadeOrigem, ref idCidadeDestino); LerRadioButtonsSelecionados(); gps.CaminhosEncontrados = new List <Caminho>(); MetodoDeBusca metodoEscolhido = gps.Metodo; switch (metodoEscolhido) { case MetodoDeBusca.Pilhas: gps.BuscarCaminhosPilhas(idCidadeOrigem, idCidadeDestino); break; case MetodoDeBusca.Recursao: gps.BuscarCaminhosRecursivo(idCidadeOrigem, idCidadeDestino); break; case MetodoDeBusca.Dijkstra: gps.BuscarCaminhosDijkstra(idCidadeOrigem, idCidadeDestino); break; } Caminho melhorCaminho = BuscarMelhorCaminho(Extensoes.Clone(gps.CaminhosEncontrados)); ExibirCaminhos(Extensoes.Clone(gps.CaminhosEncontrados), melhorCaminho); } catch (Exception ex) { MessageBox.Show(ex.Message, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
/** * Método responsável por desenhar as retas ligando cada movimento do caminho passado como parâmetro. */ private void DesenharCaminho(Caminho caminhoParaDesenhar) { if (caminhoParaDesenhar != null) { Graphics g = pbMapa.CreateGraphics(); Pen pen = new Pen(Color.Blue, 3); int xProporcional = 4096 / pbMapa.Width + 1; int yProporcional = 2048 / pbMapa.Height + 1; Caminho caminhoClone = (Caminho)caminhoParaDesenhar.Clone(); int coordenadaXOrigem = 0, coordenadaXDestino = 0, coordenadaYOrigem = 0, coordenadaYDestino = 0; while (!caminhoClone.Movimentos.EstaVazia) { foreach (Cidade c in gps.ListaCidades) { if (caminhoClone.Movimentos.Primeiro.Info.IdCidadeOrigem == c.Id) { coordenadaXOrigem = c.CoordenadaX; coordenadaYOrigem = c.CoordenadaY; } if (caminhoClone.Movimentos.Primeiro.Info.IdCidadeDestino == c.Id) { coordenadaXDestino = c.CoordenadaX; coordenadaYDestino = c.CoordenadaY; } } g.DrawLine(pen, new Point(coordenadaXOrigem / xProporcional, coordenadaYOrigem / yProporcional), new Point(coordenadaXDestino / xProporcional, coordenadaYDestino / yProporcional)); caminhoClone.RemoverMovimento(); } } }
/* * Lê os caminhos de um arquivo e adiciona na matriz do grafo. */ private void LerCaminhos(StreamReader arq) { while (!arq.EndOfStream) { Caminho caminho = Caminho.LerRegistro(arq); grafo[caminho.IdOrigem, caminho.IdDestino] = caminho.Distancia; } arq.Close(); }
/* * Adiciona um caminho a um indice determinado no dataGridView. * @params o DataGridView que iremos modificar, o caminho que iremos inserir e um inteiro chamado indice que determina * que posição ou coluna será incluido. */ private void ExibirDgv(DataGridView qualDgv, Caminho insercao, int indice) { if (indice == 0) { qualDgv[indice, qualDgv.RowCount - 1].Value = insercao.IdOrigem; } qualDgv[++indice, qualDgv.RowCount - 1].Value = insercao.IdDestino; }
void CriarGrafo() { matAdjacencias = new Caminho[qtosDados, qtosDados]; var arquivo = new StreamReader(@"CaminhosEntreCidadesMarte.txt"); while (!arquivo.EndOfStream) { Caminho c = new Caminho(arquivo.ReadLine()); matAdjacencias[c.IdCidadeOrigem, c.IdCidadeDestino] = c; } }
/* * Evento paint do pictureBox mapa que exibirá as cidades e os caminhos. Desenha os pontos em cada cidade, seguindo * PreOrdem da Árvore. Também exibe um caminho selecionado pelo usuário caso ele não seja negativo. */ private void pbMapa_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; arvore.PreOrdem((Cidade c) => { float coordenadaX = c.CoordenadaX * pbMapa.Width / TAMANHOX; float coordenadaY = c.CoordenadaY * pbMapa.Height / TAMANHOY; g.FillEllipse( new SolidBrush(Color.Black), coordenadaX, coordenadaY, 10f, 10f ); g.DrawString(c.Nome, new Font("Courier New", 8, FontStyle.Bold), new SolidBrush(Color.FromArgb(32, 32, 32)), coordenadaX + 12, coordenadaY - 10); }); if (selecionado >= 0) { PilhaLista <Caminho> aux = listaCaminhos[selecionado].Clone(); while (!aux.EstaVazia()) { Caminho possivelCaminho = aux.Desempilhar(); Cidade origem = arvore.ExisteDado(new Cidade(possivelCaminho.IdOrigem)); Cidade destino = arvore.ExisteDado(new Cidade(possivelCaminho.IdDestino)); using (var pen = new Pen(Color.FromArgb(211, 47, 47), 2)) { int origemX = origem.CoordenadaX * pbMapa.Width / TAMANHOX + 5; int origemY = origem.CoordenadaY * pbMapa.Height / TAMANHOY + 5; int destinoX = destino.CoordenadaX * pbMapa.Width / TAMANHOX + 5; int destinoY = destino.CoordenadaY * pbMapa.Height / TAMANHOY + 5; AdjustableArrowCap flecha = new AdjustableArrowCap(5, 5); if (destinoX - origemX > pbMapa.Width / 2) { g.DrawLine(pen, origemX, origemY, 0, origemY); pen.CustomEndCap = flecha; g.DrawLine(pen, pbMapa.Width, origemY, destinoX, destinoY); } else { pen.CustomEndCap = flecha; g.DrawLine(pen, origemX, origemY, destinoX, destinoY); } } } } }
/** * Método com a função de exibir os resultados para o usuário. * Percorre a lista de caminhos encontrados e de melhor caminho, exibindo cada passo em uma coluna do dataGridView. * Caso nenhuma coluna seja exibida, nenhum caminho foi encontrado e o usuário é alertado. */ private void ExibirCaminhos(List <Caminho> listaCaminhos, Caminho melhorCaminho) { dgvCaminhos.ColumnCount = 0; dgvCaminhos.RowCount = listaCaminhos.Count; int caminhosExibidos = 0; int qtdMovimentos; foreach (Caminho caminho in listaCaminhos) { qtdMovimentos = caminho.Tamanho; if (qtdMovimentos > dgvCaminhos.ColumnCount) { dgvCaminhos.ColumnCount = qtdMovimentos; // quantidade de colunas do dataGridView se iguala ao tamanho de passos do maior caminho for (int i = 0; i < qtdMovimentos; i++) { dgvCaminhos.Columns[i].HeaderText = "Cidade"; } } // exibe cada movimento do caminho em questão for (int i = qtdMovimentos - 1; !caminho.Movimentos.EstaVazia; i--) { Movimento mov = (Movimento)caminho.RemoverMovimento(); dgvCaminhos.Rows[caminhosExibidos].Cells[i].Value = mov.ToString(); } caminhosExibidos++; } if (melhorCaminho.Tamanho > 0) // se a lista de melhorCaminho não estiver vazia { qtdMovimentos = melhorCaminho.Tamanho; dgvMelhorCaminho.ColumnCount = qtdMovimentos; dgvMelhorCaminho.RowCount = 1; for (int i = qtdMovimentos - 1; !melhorCaminho.Movimentos.EstaVazia; i--) // exibe cada movimento do melhor caminho { Movimento mov = melhorCaminho.RemoverMovimento(); dgvMelhorCaminho.Rows[0].Cells[i].Value = mov.ToString(); } lbTotalMenorPercurso.Text = melhorCaminho.PesoTotal.ToString(); } else // se nenhum caminho foi encontrado, o usuário é alertado e os dataGridViews limpados { LimparPictureBox(); dgvMelhorCaminho.RowCount = 0; lbTotalMenorPercurso.Text = ""; MessageBox.Show("Não foi encontrado nenhum caminho."); } }
//Desenhando as linhas no mapa do formulário. private void DesenhaLinhas(Graphics g) { Caminho aux = null; Cidade c1 = null; Cidade c2 = null; Pen minhaCaneta = new Pen(Color.DarkGreen, 4); //Faz com que as linhas tenha setas nas pontas minhaCaneta.CustomEndCap = new AdjustableArrowCap(4, 6); //Percorre a matriz de caminhos desenhando todas as cidades e caminhos for (int linhas = 0; linhas < qtdCidades; linhas++) { for (int colunas = 0; colunas < qtdCidades; colunas++) { if (matriz[linhas, colunas] != null) { aux = matriz[linhas, colunas]; //Busca as cidades com o id na arvore c1 = arvore.BuscarDado(new Cidade(linhas)); c2 = arvore.BuscarDado(new Cidade(colunas)); //Pega as cordenadas de cada cidade para desenha-las no picture box float xI = pbMapa.Size.Width * c1.CoordenadaX / 4096; float yI = pbMapa.Size.Height * c1.CoordenadaY / 2048; float xF = pbMapa.Size.Width * c2.CoordenadaX / 4096; float yF = pbMapa.Size.Height * c2.CoordenadaY / 2048; //Onde I => Inicial, F => Final //Duas exceções, o caminho de Senzeni Na até Gondor e de Arrakeen até Gondor //As duas são caminhos que devem passar por fora do mapa, pois o planeta é uma esfera if ((c1.IdCidade == 2 || c1.IdCidade == 18) && (c2.IdCidade == 10)) { g.DrawLine(minhaCaneta, xI, yI, -xF, yF); g.DrawLine(minhaCaneta, 2048 + xI, yI, xF, yF); } else //O resto é tratado normalmente e desenhado com as coordenadas passadas { g.DrawLine(minhaCaneta, xI, yI, xF, yF); } } } } }
public void lerCaminhos() { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Lê o arquivo de caminhos e guarda os caminhos na variavel caminho String linha; arquivoCaminhos = new StreamReader("CaminhosEntreCidadesMarte.txt"); while (!arquivoCaminhos.EndOfStream) { linha = arquivoCaminhos.ReadLine(); int idCidadeOrigem = int.Parse(linha.Substring(0, 3)); int idCidadeDestino = int.Parse(linha.Substring(3, 3)); int distancia = int.Parse(linha.Substring(6, 5)); int tempo = int.Parse(linha.Substring(11, 4)); int custo = int.Parse(linha.Substring(15, 5)); Caminho caminho = new Caminho(idCidadeOrigem, idCidadeDestino, distancia, tempo, custo); caminhos[idCidadeOrigem, idCidadeDestino] = caminho; } }
/** * Método que retorna o melhor caminho entre duas cidades. * É passado como parâmetro a lista "caminhos", que representa todos os caminhos possíveis entre determinadas cidades. * Dessa forma, são declarados uma Pilha de retorno e uma matriz, que representará a matriz de adjacência. * Cada caminho da lista passada como parâmetro é percorrido e tem seu critério (distância, tempo ou custo) total calculado. * Por fim, a pilhaDeMovimentos de retorno recebe o caminho com o menor critério total e é retornado. */ public Caminho BuscarMelhorCaminho(List <Caminho> caminhos) { Caminho ret = new Caminho(); int menorPeso = 0; // critério -> distância, tempo ou custo (o que for escolhido pelo usuário) foreach (Caminho caminho in caminhos) { Caminho caminhoClone = (Caminho)caminho.Clone(); // caminhoClone para não desempilhar o caminho que deve ser retornado. int pesoTotal = 0; while (!caminhoClone.Movimentos.EstaVazia) { int idCidadeOrigem = caminhoClone.Movimentos.OTopo().IdCidadeOrigem; int idCidadeDestino = caminhoClone.Movimentos.OTopo().IdCidadeDestino; switch (this.Criterio) { case CriterioMelhorCaminho.Distancia: pesoTotal += matrizAdjacencia[idCidadeOrigem, idCidadeDestino].Distancia; break; case CriterioMelhorCaminho.Tempo: pesoTotal += matrizAdjacencia[idCidadeOrigem, idCidadeDestino].Tempo; break; case CriterioMelhorCaminho.Custo: pesoTotal += matrizAdjacencia[idCidadeOrigem, idCidadeDestino].Custo; break; } caminhoClone.RemoverMovimento(); } if (pesoTotal < menorPeso || menorPeso == 0) // se a distância total do caminho em questão for menor que todas as outras até o momento { ret = (Caminho)caminho.Clone(); menorPeso = pesoTotal; ret.PesoTotal = menorPeso; } } return(ret); }
public Marte(string cidadeMarteArquivo, string caminhosEntreMarteArquivo) { if (cidadeMarteArquivo.Trim() == null || caminhosEntreMarteArquivo.Trim() == null) { throw new Exception("Nome do arquivo null"); } if (cidadeMarteArquivo.Trim().Equals("") || caminhosEntreMarteArquivo.Trim().Equals("")) { throw new Exception("Nome do arquivo vazio"); } this.cidadeMarteArquivo = cidadeMarteArquivo; this.caminhosEntreMarteArquivo = caminhosEntreMarteArquivo; StreamReader LeitorCidade = new StreamReader(cidadeMarteArquivo); StreamReader LeitorCaminho = new StreamReader(caminhosEntreMarteArquivo); int numeroDeCidades = 0; cidades = new ArvoreCidades(); while (!LeitorCidade.EndOfStream) { string linha = LeitorCidade.ReadLine(); Cidade cidade = new Cidade(linha); cidades.Incluir(cidade); numeroDeCidades++; } matrizAdjacenteDeCaminhos = new Caminho[numeroDeCidades, numeroDeCidades]; while (!LeitorCaminho.EndOfStream) { string linha = LeitorCaminho.ReadLine(); Caminho caminho = new Caminho(linha); MatrizAdjacenteDeCaminhos[caminho.GetIdOrigem, caminho.GetIdDestino] = caminho; } }
/* * Exibe todos os caminhos em um dataGridView de caminhos e o menor caminho em um outro. */ private void MostrarCaminhos() { foreach (PilhaLista <Caminho> caminho in listaCaminhos) { int posicao = 0; PilhaLista <Caminho> aux = caminho.Clone(); aux.Inverter(); if (dgvCaminhoEncontrado.RowCount == menor) { dgvMelhorCaminho.RowCount++; dgvMelhorCaminho.ColumnCount = aux.Tamanho() + 1; } dgvCaminhoEncontrado.RowCount++; if (dgvCaminhoEncontrado.ColumnCount <= aux.Tamanho()) { dgvCaminhoEncontrado.ColumnCount = aux.Tamanho() + 1; } while (!aux.EstaVazia()) { Caminho c = aux.Desempilhar(); if (dgvCaminhoEncontrado.RowCount - 1 == menor) { ExibirDgv(dgvMelhorCaminho, c, posicao); } ExibirDgv(dgvCaminhoEncontrado, c, posicao); posicao++; } } selecionado = menor; dgvCaminhoEncontrado.Rows[selecionado].Selected = true; pbMapa.Invalidate(); }
private void EncontrarCaminhosRepeticao(int idCidadeAtual) { for (int i = 0; i < matrizAdjacenteDeCaminhos.GetLength(0); i++) { Caminho caminho = this.matrizAdjacenteDeCaminhos[idCidadeAtual, i]; if (caminho != null && !passamosAqui[i]) { aux.Add(caminho); if (i == this.idDestino) { caminhos.Add(aux.Select(item => (Caminho)item.Clone()).ToList()); } else { passamosAqui[caminho.GetIdDestino] = true; EncontrarCaminhosRepeticao(caminho.GetIdDestino); passamosAqui[caminho.GetIdDestino] = false; } aux.RemoveAt(aux.Count - 1); } } }
public void lerArquivos() { StreamReader leitor = new StreamReader("F:\\ED2\\Projeto2_DirigiveisEmMarte\\CidadesMarte.txt", Encoding.UTF7, true); string linha = leitor.ReadLine(); cidades.Raiz = new NoArvore <Cidade>(new Cidade(linha)); while (!leitor.EndOfStream) { linha = leitor.ReadLine(); cidades.Incluir(new Cidade(linha)); } leitor.Close(); rotasMatriz = new int[cidades.QuantosDados + 1, cidades.QuantosDados + 1]; leitor = new StreamReader("F:\\ED2\\Projeto2_DirigiveisEmMarte\\CidadesMarteOrdenado.txt", Encoding.UTF7, true); int indice = 1; rotasMatriz[0, 0] = -1; while (!leitor.EndOfStream) { linha = leitor.ReadLine(); Cidade nova = new Cidade(linha); cidades.Atual = new NoArvore <Cidade>(nova); rotasMatriz[indice, 0] = nova.Cod; rotasMatriz[0, indice] = nova.Cod; lsbOrigem.Items.Add(nova.Cod + " - " + nova.Nome); lsbDestino.Items.Add(nova.Cod + " - " + nova.Nome); indice++; } leitor.Close(); leitor = new StreamReader("F:\\ED2\\Projeto2_DirigiveisEmMarte\\CaminhosEntreCidadesMarte.txt", Encoding.UTF7, true); while (!leitor.EndOfStream) { linha = leitor.ReadLine(); Caminho novo = new Caminho(linha); caminhos.InserirAposFim(novo); for (int i = 1; i < cidades.QuantosDados + 1; i++) { if (i - 1 == novo.CodOrigem) { for (int a = 1; a < cidades.QuantosDados + 1; a++) { if (a - 1 == novo.CodDestino) { rotasMatriz[i, a] = novo.Distancia; } } } } } leitor.Close(); quantosdados = cidades.QuantosDados; cidades.OndeExibir = tpArvore; }
//Método que, efetivamente, busca caminhos entre as cidades do mapa. private void BtnBuscar_Click(object sender, EventArgs e) { //Variáveis para operações do btnBuscar. int idCidadeOrigem = lsbOrigem.SelectedIndex; int idCidadeDestino = lsbDestino.SelectedIndex; int cidadeAtual = idCidadeOrigem; int saidaAtual = 0; bool[] passou = new bool[qtdCidades]; bool achou = false; bool acabou = false; List <PilhaLista <Caminho> > caminhosValidos = new List <PilhaLista <Caminho> >(); PilhaLista <Caminho> p = new PilhaLista <Caminho>(); for (int i = 0; i < qtdCidades; i++) //Inicia os valores de “passou” { passou[i] = false; //Pois ainda não foi em nenhuma cidade } int indice = 0; while (!acabou) //Enquanto não acabou { while ((saidaAtual < qtdCidades) && !achou) { //Se não há saida pela cidade testada, verifica a próxima. if (matriz[cidadeAtual, saidaAtual] == null) { saidaAtual++; } else //Se já passou pela cidade testada, verifica se a próxima //cidade permite saída. if (passou[saidaAtual]) { saidaAtual++; } else //Se chegou na cidade desejada, empilha o local //e termina o processo de procura de caminho. if (saidaAtual == idCidadeDestino) //Se a saída é o id do destino, { p.Empilhar(new Caminho(cidadeAtual, saidaAtual)); //Encontramos o destino. achou = true; } else { p.Empilhar(new Caminho(cidadeAtual, saidaAtual)); //Vamos a outra cidade, isto é, à cidade de saída. passou[cidadeAtual] = true; cidadeAtual = saidaAtual; saidaAtual = 0; } } if (!achou) { if (!p.EstaVazia()) { //Backtracking --> Retorna o caminho. Caminho aux = p.Desempilhar(); saidaAtual = aux.IdCidadeDestino; passou[saidaAtual] = false; cidadeAtual = aux.IdCidadeOrigem; aux = null; saidaAtual++; } else { acabou = true; } } if (achou) { //Desempilha a configuração atual da pilha //Para a pilha da lista de parâmetros caminhosValidos.Add(new PilhaLista <Caminho>()); PilhaLista <Caminho> auxiliar = new PilhaLista <Caminho>(); while (!p.EstaVazia()) { auxiliar.Empilhar(p.Desempilhar()); //Invertemos os caminhos. caminhosValidos[indice].Empilhar(auxiliar.OTopo()); } while (!auxiliar.EstaVazia()) { p.Empilhar(auxiliar.Desempilhar()); } indice++; achou = false; //Backtracking --> Retorna o caminho. Caminho aux = p.Desempilhar(); saidaAtual = aux.IdCidadeDestino; passou[saidaAtual] = false; cidadeAtual = aux.IdCidadeOrigem; aux = null; saidaAtual++; } } //Método que mostra todos os caminhos no dgvCaminho. TodosOsCaminhos(caminhosValidos, idCidadeOrigem, idCidadeDestino); }
void BuscarCaminhos(int cdOrigem, int cdDestino) { if (cdOrigem != cdDestino) { bool achouTodos = false; bool[] passouCidade = new bool[qtosDados + 1]; int c = 0; PilhaLista <Caminho> caminhos = new PilhaLista <Caminho>(); caminhosDescobertos = new PilhaLista <PilhaLista <Caminho> >(); for (int i = 0; i < qtosDados; i++) { passouCidade[i] = false; } do { if (cdOrigem == cdDestino || c >= qtosDados) { if (caminhos.EstaVazia()) { achouTodos = true; } else { if (cdOrigem == cdDestino) { caminhosDescobertos.Empilhar(caminhos.Copia()); } Caminho caminho = caminhos.Desempilhar(); cdOrigem = caminho.IdCidadeOrigem; passouCidade[caminho.IdCidadeDestino] = false; if (caminho.IdCidadeDestino != caminho.IdCidadeOrigem) { c = caminho.IdCidadeDestino + 1; } } } if (c < qtosDados && matAdjacencias[cdOrigem, c] != null) { if (passouCidade[c] != true) { passouCidade[cdOrigem] = true; caminhos.Empilhar(matAdjacencias[cdOrigem, c]); cdOrigem = c; c = -1; // recebe -1, pois incrementa logo após } } c++; }while (!achouTodos); ExibirCaminhos(caminhosDescobertos); if (!caminhosDescobertos.EstaVazia()) { AcharMelhorCaminho(caminhosDescobertos); } } else if (cdOrigem != -1 && cdDestino != -1) { MessageBox.Show("Você já está na cidade!"); } }
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; } } } } }